home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
network
/
samba
/
patches
/
samba-1.036
/
samba-1
Wrap
Text File
|
1995-11-14
|
157KB
|
5,332 lines
diff -u -r --new-file last-version/docs/BROWSING.txt samba-1.9.15/docs/BROWSING.txt
--- last-version/docs/BROWSING.txt Tue Jan 10 22:05:51 1995
+++ samba-1.9.15/docs/BROWSING.txt Tue Nov 14 22:29:10 1995
@@ -1,18 +1,17 @@
BROWSING
========
-Samba has recently begun support for browsing. The browsing is
-supported by nmbd and is also controlled by options in the smb.conf
-file (see smb.conf(5)).
-
-Samba does not act as a browse master for a workgroup, so it can only
-participate in workgroups which already have a browse master. If you
-have any WfWg or WinNT machines in your workgroup that exports a share
-then you already have a browse master so this shouldn't be a problem.
-
-To get browsing to work you need to run nmbd as usual, but need to
-either give the -G option to elect which workgroup Samba will be part
-of, or use a lmhosts file.
+Samba now fully supports browsing. The browsing is supported by nmbd
+and is also controlled by options in the smb.conf file (see
+smb.conf(5)).
+
+Samba can act as a browse master for a workgroup, but currently cannot
+act as a domain controller. The ability to be a domain controller will
+be added in a later version.
+
+To get browsing to work you need to run nmbd as usual, but will need
+to use the "workgroup" option in smb.conf to control what workgroup
+Samba becomes a part of.
The -G option is most useful for simple setups where Samba is browsable
in only one workgroup. In more complex cases the lmhosts file is
@@ -33,7 +32,12 @@
# our own net address
0.0.0.0 MYGROUP G
-Samba has a useful option for a Samba server to offer itself for
+Note in the above that I overrode what workgroup Samba is in using the
+G flag. Also note that the 0.0.0.0 address is used, which will be
+automatically replaced with the broadcast address for groups, and with
+the local IP address for other entries.
+
+Samba also has a useful option for a Samba server to offer itself for
browsing on another subnet.
This works by the lmhosts file specifying a broadcast address on the
@@ -44,25 +48,19 @@
do the trick:
# put ourselves in the STAFF workgroup on the other subnet
-192.0.3.255 STAFF S
-
-Notice the S at the end! It is very important you include this as this
-entry without the S could cause a broadcast storm!
+192.0.3.255 STAFF G
-If browsing is causing you trouble you can disable it with the -b
-option to nmbd.
+Notice the G at the end! It is very important you include this as this
+entry without the G could cause a broadcast storm!
-If something doesn't work then hopefully the log.nmb.debug file will
-help you track down the problem.
+If something doesn't work then hopefully the log.nmb file will
+help you track down the problem. Try a debug level of 2 or 3 for
+finding problems.
Note that if it doesn't work for you, then you should still be able to
type the server name as \\SERVER in filemanager then hit enter and
filemanager should display the list of available shares.
-Remember: Samba can only participate in EXISTING workgroups. If you specify
-a workgroup that dosn't exist then browsing won't work. In future versions
-Samba will probably be able to create it's own workgroups.
-
Some people find browsing fails because they don't have the global
"guest account" set to a valid account. Remember that the IPC$
connection that lists the shares is done as guest, and thus you must
@@ -75,36 +73,34 @@
are now far more likely to correctly find your broadcast and network
addess, so in most cases these aren't needed.
-
-FINDING A MASTER BROWSER
-========================
-
-Often people find that nmbd has trouble finding a master browser. The
-likely causes of this problem are:
+The other big problem people have is that their broadcast address,
+netmask or IP address is wrong (specified with the -B, -N and -I
+options to nmbd).
-1) you are using the wrong broadcast address
-
-2) You are using the wrong workgroup name
-
-3) You don't have a master browser.
-
-To find out which of the above problems applies to you use the -M
-switch to nmbd to search for a master browser manually. eg:
+FORCING SAMBA TO BE THE MASTER
+==============================
-nmbd -M FOOGROUP -B a.b.c.d
+Who becomes the "master browser" is determined by an election process
+using broadcasts. Each election packet contains a number of parameters
+which determine what precedence (bias) a host should have in the
+election. By default Samba uses a very low precedence and thus loses
+elections to just about anyone else.
+
+If you want Samba to win elections then just set the "os level" global
+option in smb.conf to a higher number. It defaults to 0. Using 3 would
+make it win all elections over every other system (except other samba
+systems!)
-This will look for a master browser for the workgroup FOOGROUP using
-broadcast a.b.c.d. When you successfully find a master browser you
-know you have the broadcast and group name right.
+A "os level" of 2 would make it beat WfWg and Win95, but not NTAS.
NOTE ABOUT BROADCAST ADDRESSES
==============================
If your network uses a "0" based broadcast address (for example if it
-ends in a 0) then you may strike problems. Windows for Workgroups does
-not seem to support a 0's broadcast and you will probably find that
-browsing and name lookups won't work.
+ends in a 0) then you will strike problems. Windows for Workgroups
+does not seem to support a 0's broadcast and you will probably find
+that browsing and name lookups won't work.
You have a few options:
@@ -112,7 +108,9 @@
.255 (check with your local network guru for details)
2) set the nmbd broadcast to a 1's based address on the command line using
-the -B option.
+the -B option. This only works if your network setup listens on both
+0s and 1s based broadcasts. The -B option can only control what
+address it sends to, not what it listens on.
+
-3) explicitly support both broadcasts with two entries in your lmhosts file.
diff -u -r --new-file last-version/docs/DIAGNOSIS.txt samba-1.9.15/docs/DIAGNOSIS.txt
--- last-version/docs/DIAGNOSIS.txt Sat Nov 11 14:19:09 1995
+++ samba-1.9.15/docs/DIAGNOSIS.txt Tue Nov 14 22:41:04 1995
@@ -36,8 +36,8 @@
read only = yes
-These tests also assume version 1.9.14 or later of the samba suite. If
-you have version 1.9.13 then see "NOTE 1" below.
+THESE TESTS ASSUME VERSION 1.9.15 OR LATER OF THE SAMBA SUITE. SOME
+COMMANDS SHOWN DID NOT EXIST IN EARLIER VERSIONS
TEST 1:
@@ -91,11 +91,8 @@
TEST 4:
-------
-run the command "nmbd -L __SAMBA__ -B BIGSERVER". You should get a
-bunch of info back including the string "got a positive name query
-response". You should also see a message "got a positive node status
-response" and below that a list of netbios names. The name BIGSERVER
-should be included in that list.
+run the command "nmblookup -B BIGSERVER __SAMBA__". You should get the
+IP address of your Samba server back.
If you don't then nmbd is incorrectly installed. Check your inetd.conf
if yu run it from there, or that the daemon is running and listening
@@ -109,40 +106,41 @@
TEST 5:
-------
-run the command "nmbd -L '*' -B ACLIENT"
+run the command "nmblookup -B ACLIENT '*'"
-You should get a "positive name query response" from the PC. If you
-don't then the client software on the PC isn't installed correctly, or
-isn't started, or you got the name of the PC wrong. Note that you
-probably won't get a "node status response" from the PC due to a bug
-in the microsoft netbios nameserver implementation (it responds to the
-wrong port number).
+You should get the PCs IP address back. If you don't then the client
+software on the PC isn't installed correctly, or isn't started, or you
+got the name of the PC wrong. Note that you probably won't get a "node
+status response" from the PC due to a bug in the microsoft netbios
+nameserver implementation (it responds to the wrong port number).
TEST 6:
-------
-run the command "nmbd -L '*'"
+run the command "nmblookup -d 2 '*'"
This time we are trying the same as the previous test but are trying
-it via a broadcast to the default broadcast address. All Netbios/TCPIP
-hosts on the network should respond, although Samba may not catch all
-of the responses in the short time it listens.
-
-If this doesn't give a similar result to the previous test then nmbd
-isn't correctly getting your broadcast address through its automatic
-mechanism. In this case you should experiment with the -B option which
-allows you to manually specify the broadcast address, overriding the
-automatic detection. You should try different broadcast addresses
-until your find the one that works. It will most likely be something
-like a.b.c.255 as microsoft tcpip stacks only listen on 1's based
-broadcast addresses. If you get stuck then ask your local networking
-guru for help (and show them this paragraph).
+it via a broadcast to the default broadcast address. A number of
+Netbios/TCPIP hosts on the network should respond, although Samba may
+not catch all of the responses in the short time it listens. You
+should see "got a positive name query response" messages from several
+hosts.
+
+If this doesn't give a similar result to the previous test then
+nmblookup isn't correctly getting your broadcast address through its
+automatic mechanism. In this case you should experiment with the -B
+option which allows you to manually specify the broadcast address,
+overriding the automatic detection. You should try different broadcast
+addresses until your find the one that works. It will most likely be
+something like a.b.c.255 as microsoft tcpip stacks only listen on 1's
+based broadcast addresses. If you get stuck then ask your local
+networking guru for help (and show them this paragraph).
If you find you do need the -B option (ie. the automatic detection
doesn't work) then you should add the -B option with the right
broadcast address for your network to the command line of nmbd in
inetd.conf or in the script you use to start nmbd as a daemon. Once
-you do this go back to the "nmbd -L __SAMBA__ -B BIGSERVER" test to
+you do this go back to the "nmblookup __SAMBA__ -B BIGSERVER" test to
make sure you have it running properly.
If your PC and server aren't on the same subnet then you will need to
@@ -152,16 +150,6 @@
TEST 7:
-------
-run the command "nmbd -M -"
-
-this should find a master browser on your network. If you don't have
-one then browsing won't work with samba. See the file BROWSING.txt for
-details. Note that you may need the -B option to the command if the
-previous test showed that the default broadcast is incorrect.
-
-TEST 8:
--------
-
run the command "smbclient '\\BIGSERVER\TMP'". You should then be
prompted for a password. You should use the password of the account
you are logged into the unix box with. If you want to test with
@@ -187,7 +175,7 @@
when you type "dir".
-TEST 9:
+TEST 8:
-------
On the PC type the command "net view \\BIGSERVER". You will need to do
@@ -212,7 +200,7 @@
pages)
-TEST 10:
+TEST 9:
--------
run the command "net use x: \\BIGSERVER\TMP". You should be prompted
@@ -228,7 +216,7 @@
fixes things you may need the username mapping option.
-TEST 11:
+TEST 10:
--------
From file manager try to browse the server. Your samba server should
@@ -246,18 +234,4 @@
Try the mailing list or newsgroup, or use the tcpdump-smb utility to
sniff the problem.
-
-ADDITIONAL NOTES
-----------------
-
-NOTE 1:
-
-If you have version 1.9.13 of Samba then the "nmbd -L ACLIENT -B
-ACLIENT" test may fail if your client doesn't export any shares. To
-fix this either export a share or change the "lookup_type" in
-nameserv.c from ' ' to 0 and recompile.
-
-Also the "wildcard" lookup capability used in the command "nmbd -L
-'*'" was only added in 1.9.14. If you have 1.9.13 then use a clients
-netbios name instead (for example "nmbd -L ACLIENT").
diff -u -r --new-file last-version/docs/HINTS.txt samba-1.9.15/docs/HINTS.txt
--- last-version/docs/HINTS.txt Wed Apr 26 16:36:44 1995
+++ samba-1.9.15/docs/HINTS.txt Tue Nov 14 22:41:54 1995
@@ -124,19 +124,6 @@
Often WfWg will totally ignore a password you give it in a dialog box.
-
------------------------
-HINT: Getting WfWg to be a master browser
-
-Apart from exporting a drive, you should be able to get WfWg to be a
-master browser by using:
-
-[Network]
-MaintainServerList=YES
-
-in the system.ini file
-
-
----------------------
HINT: Using MS Access
diff -u -r --new-file last-version/docs/INSTALL.txt samba-1.9.15/docs/INSTALL.txt
--- last-version/docs/INSTALL.txt Fri Jul 7 08:30:27 1995
+++ samba-1.9.15/docs/INSTALL.txt Tue Nov 14 22:55:40 1995
@@ -50,11 +50,14 @@
The simplest useful configuration file would be something like this:
[homes]
+ workgroup = MYGROUP
guest ok = no
read only = no
which would allow connections by anyone with an account on the server,
-using either their login name or "homes" as the service name.
+using either their login name or "homes" as the service name. (Note
+that I also set the workgroup that Samba is part of. See BROWSING.txt
+for defails)
Note that "make install" will not install a smb.conf file. You need to
create it yourself. You will also need to create the path you specify
@@ -147,7 +150,7 @@
also be used to see what shares are available on other LanManager
clients (such as WfWg).
-If you chose user level security then you may find that Samba requests
+If you choose user level security then you may find that Samba requests
a password before it will list the shares. See the smbclient docs for
details. (you can force it to list the shares without a password by
adding the option -U% to the command line. This will not work with
@@ -199,72 +202,21 @@
documentation (or source code) so that the next person will find it
easier.
+DIAGNOSING PROBLEMS
+===================
-TESTING NMBD
-============
+If you have instalation problems then go to DIAGNOSIS.txt to try to
+find the problem.
-As of version 1.7.00 it is possible to test nmbd to see if it is
-correctly installed. This can also test to see if it can auto-detect
-your broadcast address.
-
-Under some operating systems you can only test the broadcast part if
-running as root. You can test other functionality from a non-root
-account. To test from root use:
-
-nmbd -L TESTNAME
-
-where TESTNAME is the netbios name you wish to test. This would
-typically be the hostname of the unix host where you installed nmbd.
-It should return the IP address of the host you are looking for. If it
-doesn't then something is wrong with your nmbd configuration. (It is
-also possibe that you have a net configuration that doesn't send
-broadcasts to itself. Some Linux configurations do this.)
-
-If it fails then it could mean it is not correctly detecting your
-broadcast address or netmask. You will then need to supply the -B and
--N parameters. See the nmbd man page for details.
-
-It has succeeded if somewhere in the output is a line like:
-
-ww.xx.yy.zz HOSTNAME
-
-which means it managed to look the IP correctly.
-
-To test from a non-root account use:
-
-nmbd -B HOSTNAME -L TESTNAME
-
-where hostname is the host name of the host where nmbd is installed
-and TESTNAME is the name you want to test. Typically this would be the
-same as HOSTNAME.
-
-
-NAME RESOLUTION
-===============
-
-Probably the most common problem people have when installing Samba is
-getting name resolution to work. This is usually caused by incorrect
-settings for nmbd.
-
-One solution is to use nmbd as a WINS server, instead of using name
-resolution by broadcast. To do this you need to enter the IP address
-of the Samba server in the WINS section of your WfWg, Win95 or WinNT TCP/IP
-setup.
-
-As a last resort you can use a lmhosts file on the PC to resolve names,
-as long as you enable lmhosts name resolution in the right dialog
-box. This doesn't lend itself very well to update, however.
-
-The best solution is, however, to fix the nmbd setup. Experimentation
-and careful reading of the Samba docs should help.
-
SCOPE IDs
=========
By default Samba uses a blank scope ID. This means all your windows
boxes must also have a blank scope ID. If you really want to use a
non-blank scope ID then you will need to use the -i <scope> option to
-nmbd, smbd, and smbclient.
+nmbd, smbd, and smbclient. All your PCs will need to have the same
+setting for this to work. I do not recommend scope IDs.
+
CHOOSING THE PROTOCOL LEVEL
===========================
@@ -350,9 +302,9 @@
DENY_NONE, DENY_READ, DENY_WRITE or DENY_ALL. There are also special
compatability modes called DENY_FCB and DENY_DOS.
-By default Samba does not implement these share modes. If you use
-"share modes = yes" then Samba will implement them using locking files
-in the "lock directory". See the man pages for details.
+You can disable share modes using "share modes = no". This may be
+useful on a heavily loaded server as the share modes code is very
+slow.
MAPPING USERNAMES
diff -u -r --new-file last-version/docs/MIRRORS samba-1.9.15/docs/MIRRORS
--- last-version/docs/MIRRORS Fri Sep 15 19:02:39 1995
+++ samba-1.9.15/docs/MIRRORS Mon Nov 13 08:31:20 1995
@@ -8,7 +8,7 @@
ftp://sunsite.unc.edu/pub/Linux/system/Network/Samba/
ftp://ftp.choc.apana.org.au/pub/samba
ftp://ftp.uni-trier.de/pub/unix/network/samba/
-
+ftp://ftp.spectrum.titan.com/pub/samba
There are several others. Give archie a try.
diff -u -r --new-file last-version/docs/nmbd.8 samba-1.9.15/docs/nmbd.8
--- last-version/docs/nmbd.8 Mon Apr 17 18:27:52 1995
+++ samba-1.9.15/docs/nmbd.8 Tue Nov 14 22:33:04 1995
@@ -20,23 +20,9 @@
.B -H
.I netbios hosts file
] [
-.B -L
-.I netbios name
-] [
-.B -M
-.I workgroup name
-] [
.B -N
.I netmask
] [
-.B -P
-] [
-.B -R
-] [
-.B -b
-] [
-.B -S
-] [
.B -d
.I debuglevel
] [
@@ -46,22 +32,17 @@
.B -n
.I netbios name
] [
-.B -O
-.I socket options
-] [
.B -p
.I port number
-] [
-.B -T
-.I browse interval
]
+
.SH DESCRIPTION
This program is part of the Samba suite.
.B nmbd
is a server that understands and can reply to netbios
name service requests, like those produced by LanManager
-clients.
+clients. It also controls browsing.
LanManager clients, when they start up, may wish to locate a LanManager server.
That is, they wish to know what IP number a specified host is using.
@@ -82,11 +63,6 @@
means is that it will respond to all name requests that it receives
that are not broadcasts, as long as it can resolve the name.
.SH OPTIONS
-.B -b
-
-.RS 3
-This toggles support for browsing from WfWg. It defaults to on.
-.RE
.B -B
.RS 3
@@ -172,7 +148,7 @@
from the -G option) are registered on the network (unless the -R
option has been selected).
-A S means that the specified address is a broadcast address of a
+A S or G means that the specified address is a broadcast address of a
network that you want people to be able to browse you from. Nmbd will
search for a master browser in that domain and will send host
announcements to that machine, informing it that the specifed somain
@@ -209,7 +185,7 @@
# now we want another subnet to be able to browse
# us in the workgroup UNIXSERV
- 192.0.2.255 UNIXSERV S
+ 192.0.2.255 UNIXSERV G
.RE
@@ -229,33 +205,6 @@
as a daemon or in inetd.
.RE
-.B -L
-.I netbios name
-
-.RS 3
-If this parameter is given, the server will look up the specified
-.I netbios name,
-report success or failure, then exit. If successful, the IP address of the
-name located will be reported. This is useful for determining whether
-a netbios name is in use on a subnet and for matching IP addresses to netbios
-names.
-
-This option is meant to be used interactively on the command line, not
-as a daemon or in inetd.
-
-Use of this parameter causes options
-.B -D
-,
-.B -P
-,
-.B -R
-and
-.B -n
-to be ignored.
-
-By default, the server will NOT do this.
-.RE
-
.B -N
.RS 3
@@ -272,28 +221,6 @@
number.
.RE
-.B -P
-
-.RS 3
-If specified, this parameter causes the server to operate passively. That is,
-it continues to field requests, but will not respond.
-
-By default, the server will NOT operate passively.
-.RE
-
-.B -S
-
-.RS 3
-If specified, this parameter causes the server to respond to broadcast
-name queries for hosts that can be found with the gethostbyname() call
-(which normally goes to NIS or DNS). It will NOT respond if the host
-being queried is on the same subnet as the server. This is useful so
-clients can connect to servers to which they cannot broadcast.
-
-By default, the server will NOT respond to any broadcast queries other
-than it's own name.
-.RE
-
.B -d
.I debuglevel
.RS 3
@@ -351,13 +278,6 @@
name of the host on which the server is running.
.RE
-.B -O
-.I socket options
-.RS 3
-
-See the socket options section of smb.conf(5) for details
-
-.RE
.B -p
.I port number
.RS 3
@@ -377,13 +297,6 @@
This parameter is not normally specified except in the above situation.
.RE
-.B -T
-.I browse interval
-.RS 3
-
-This sets the number of seconds between browse announcements. It
-defaults to 60 seconds. The minimum value is 10 seconds.
-
.SH FILES
.B /etc/inetd.conf
diff -u -r --new-file last-version/docs/smb.conf.5 samba-1.9.15/docs/smb.conf.5
--- last-version/docs/smb.conf.5 Sun Nov 5 11:35:38 1995
+++ samba-1.9.15/docs/smb.conf.5 Tue Nov 14 22:47:42 1995
@@ -366,6 +366,8 @@
null passwords
+os level
+
packet size
passwd chat
@@ -376,6 +378,8 @@
password server
+preferred master
+
preload
printing
@@ -1492,6 +1496,10 @@
.B Example:
null passwords = yes
+.SS os level (G)
+This integer value controls what level Samba advertises itself as for
+browse elections. See BROWSING.txt for details.
+
.SS packet size (G)
The maximum transmit packet size during a raw read. This option is no
longer implemented as of version 1.7.00, and is kept only so old
@@ -1693,6 +1701,13 @@
.B Example:
preexec = echo \"%u connected to %S from %m (%I)\" >> /tmp/log
+.SS preferred master (G)
+This boolean parameter controls if Samba is a preferred master browser
+for its workgroup. Setting this gives it a slight edge in elections
+and also means it will automatically start an election when it starts
+up.
+
+It is on by default.
.SS preload
This is an alias for "auto services"
diff -u -r --new-file last-version/source/Makefile samba-1.9.15/source/Makefile
--- last-version/source/Makefile Sun Nov 12 12:56:19 1995
+++ samba-1.9.15/source/Makefile Tue Nov 14 21:28:52 1995
@@ -425,7 +425,7 @@
LIBS = $(LIBS1) $(LIBSM) $(DCE_LIBS) $(DES_LIB)
PROGS1 = smbd smbclient nmbd testparm testprns smbrun smbstatus smbpasswd
-PROGS = $(PROGS1) nmbd2 nmblookup
+PROGS = $(PROGS1) nmblookup
SCRIPTS = smbtar
all : CHECK $(PROGS)
@@ -462,17 +462,13 @@
@echo Linking smbrun
@$(CC) $(CFLAGS) -o smbrun smbrun.o $(LIBS)
-nmbd: nameserv.o $(UTILOBJ)
- @echo Linking nmbd
- @$(CC) $(CFLAGS) -o nmbd nameserv.o $(UTILOBJ) $(LIBS)
-
nmblookup: nmblookup.o $(UTILOBJ)
@echo Linking nmblookup
@$(CC) $(CFLAGS) -o nmblookup nmblookup.o nmblib.o $(UTILOBJ) $(LIBS)
-nmbd2: nameserv2.o nmblib.o $(UTILOBJ)
- @echo Linking nmbd2
- @$(CC) $(CFLAGS) -o nmbd2 nameserv2.o nmblib.o $(PARAMOBJ) $(LIBS)
+nmbd: nameserv.o nmblib.o $(UTILOBJ)
+ @echo Linking nmbd
+ @$(CC) $(CFLAGS) -o nmbd nameserv.o nmblib.o $(PARAMOBJ) $(LIBS)
smbclient: client.o clitar.o getsmbpass.o $(UTILOBJ)
@echo Linking smbclient
diff -u -r --new-file last-version/source/change-log samba-1.9.15/source/change-log
--- last-version/source/change-log Sun Nov 12 21:41:40 1995
+++ samba-1.9.15/source/change-log Tue Nov 14 23:17:02 1995
@@ -1591,7 +1591,7 @@
- added force_user to conn struct
-2.0.0:
+1.9.15: 14/11/95
- removed bcast override from workgroup announce in nmbd
- aix patch, added NO_SYSMOUNTH, from
lionel leston <102624.346@compuserve.com>
@@ -1645,11 +1645,30 @@
- added browse mastering code
- started integration with smb.conf for nmbd2
- released p5
+ - fixed death_time (should be t+ttl*3)
+ - fixed non-removal of dead servers
+ - added smbstatus -u patch from oskarh@spornet.is (Oskar Hannesson)
+ - NETGROUP fix from J.W.Schilperoort@research.kpn.com
+ - select and NO_SETGROUPS patches from lennylim@netcom.com (Lenny
+ Lim)
+ - added LINKS_READ_ONLY define in dos_mode() for LM/X
+ compatability
+ - "dir a.c" bug fixed thanks to roderich@nodebonn.muc.bmw.de
+ (Roderich Schupp)
+ - job cancel fix in client from peo@mtek.chalmers.se
+ - changed nmbd2 to nmbd
+ - fixed "dir a*" under trans2 lookups
+ - added StrnCaseCmp()
+ - updated docs a bit for new browsing stuff
+ - updated INSTALL.txt
+ - hopefully fixed server level security with WfWg
==========
todo:
+dup/close 0 for getopt?
+
implement SMBmove and SMBcopy ??
add option to print more info about locked files (full path, share name
@@ -1659,8 +1678,6 @@
no refresh/reg of new IP? or send wack and challenge owner?
-new nmb.conf file
-
protocol drop back in client to avoid openX etc.
very slow listing CD, perhaps because of order of stat and readdir?
@@ -1688,4 +1705,10 @@
ALLOW_PASSWORD_CHANGE only compiles/works on some systems
weird foooooooo/open.exe bug on NT
+
+
+lpd stuff:
+ Tony Aiuto (tony@ics.com)
+
+
diff -u -r --new-file last-version/source/client.c samba-1.9.15/source/client.c
--- last-version/source/client.c Sat Nov 11 15:23:12 1995
+++ samba-1.9.15/source/client.c Tue Nov 14 21:54:30 1995
@@ -615,7 +615,7 @@
{
if (!((finfo->mode & aDIR) == 0 && *fileselection &&
- !mask_match(finfo->name,fileselection,False,True)) &&
+ !mask_match(finfo->name,fileselection,False,False)) &&
!(recurse_dir && (strequal(finfo->name,".") ||
strequal(finfo->name,".."))))
{
@@ -2155,7 +2155,7 @@
p = skip_string(p,1);
strcpy(p,"");
p = skip_string(p,1);
- SSVAL(p,0,0); /* level 0 */
+ SSVAL(p,0,job);
p += 2;
if (call_api(PTR_DIFF(p,param),0,
diff -u -r --new-file last-version/source/includes.h samba-1.9.15/source/includes.h
--- last-version/source/includes.h Sun Nov 12 12:31:47 1995
+++ samba-1.9.15/source/includes.h Tue Nov 14 22:10:06 1995
@@ -762,6 +762,9 @@
#define getpass(s) getsmbpass(s)
#endif
+#ifndef FD_SETSIZE
+#define FD_SETSIZE 255
+#endif
#ifndef MAXINT
#define MAXINT ((((unsigned)1)<<(sizeof(int)*8-1))-1)
@@ -969,6 +972,7 @@
#ifdef NOSTRCASECMP
#define strcasecmp(s1,s2) StrCaseCmp(s1,s2)
+#define strncasecmp(s1,s2,n) StrnCaseCmp(s1,s2,n)
#endif
#ifndef strcpy
diff -u -r --new-file last-version/source/loadparm.c samba-1.9.15/source/loadparm.c
--- last-version/source/loadparm.c Sun Nov 12 13:12:57 1995
+++ samba-1.9.15/source/loadparm.c Wed Nov 15 00:05:39 1995
@@ -142,6 +142,8 @@
int printing;
int maxdisksize;
int lpqcachetime;
+ int os_level;
+ BOOL bPreferredMaster;
BOOL bEncryptPasswords;
BOOL bStripDot;
BOOL bNullPasswords;
@@ -388,6 +390,8 @@
#ifdef KANJI
{"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
#endif /* KANJI */
+ {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL},
+ {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
{"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL},
@@ -529,6 +533,9 @@
Globals.bReadbmpx = True;
Globals.bNullPasswords = False;
Globals.bStripDot = False;
+ Globals.os_level = 0;
+ Globals.bPreferredMaster = True;
+
#ifdef KANJI
coding_system = interpret_coding_system (KANJI, SJIS_CODE);
#endif /* KANJI */
@@ -636,6 +643,7 @@
FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
+FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
@@ -648,6 +656,7 @@
FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
+FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
@@ -834,7 +843,7 @@
sprintf(comment,"Home directory of %s",pszHomename);
string_set(&iSERVICE(i).comment,comment);
}
- iSERVICE(i).bAvailable = True;
+ iSERVICE(i).bAvailable = sDefault.bAvailable;
iSERVICE(i).bBrowseable = sDefault.bBrowseable;
DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
diff -u -r --new-file last-version/source/loadparm.h samba-1.9.15/source/loadparm.h
--- last-version/source/loadparm.h Sun Nov 12 13:08:34 1995
+++ samba-1.9.15/source/loadparm.h Tue Nov 14 20:59:30 1995
@@ -56,10 +56,12 @@
extern char *lp_magicscript(int iService);
extern char *lp_magicoutput(int iService);
extern char *lp_mangled_map(int iService);
+extern int lp_os_level(void);
extern int lp_max_log_size(void);
extern int lp_maxxmit(void);
extern int lp_maxmux(void);
extern int lp_mangledstack(void);
+extern BOOL lp_preferred_master(void);
extern BOOL lp_getwdcache(void);
extern BOOL lp_use_rhosts(void);
extern BOOL lp_readprediction(void);
diff -u -r --new-file last-version/source/nameserv.c samba-1.9.15/source/nameserv.c
--- last-version/source/nameserv.c Sun Nov 12 12:08:18 1995
+++ samba-1.9.15/source/nameserv.c Tue Nov 14 21:40:25 1995
@@ -1,7 +1,7 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
- NBT netbios routines and daemon
+ NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1995
This program is free software; you can redistribute it and/or modify
@@ -17,83 +17,94 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
*/
#include "includes.h"
+#include "loadparm.h"
+#include "nameserv.h"
-extern pstring debugf;
+
+static void queue_packet(struct packet_struct *packet);
+void process(void);
+static void dump_names(void);
+static void announce_request(char *group);
+
extern int DEBUGLEVEL;
-extern pstring scope;
+extern pstring debugf;
+pstring servicesf = CONFIGFILE;
-static int browse_interval = BROWSE_INTERVAL;
+extern pstring scope;
-BOOL browse = True;
-BOOL dns_serve = False;
+extern BOOL CanRecurse;
-extern struct in_addr lastip;
-extern int lastport;
extern struct in_addr myip;
extern struct in_addr bcast_ip;
extern struct in_addr Netmask;
extern pstring myhostname;
static pstring host_file;
static pstring myname="";
-static int num_good_sends=0;
-static int num_good_receives=0;
-static pstring lookup="";
-static int Client138=-1;
-enum name_sources {LMHOSTS, REGISTER, SELF, DNS};
-
-/* this is the structure used for the local netbios name table */
-typedef struct
-{
- time_t start_time;
- int ttl;
- struct in_addr ip;
- struct in_addr master_ip;
- BOOL found_master;
- BOOL valid;
- BOOL isgroup;
- BOOL unicast;
- char name[100];
- int type;
- int count;
- enum name_sources source;
-} name_struct;
+static int ClientNMB=-1;
+static int ClientDGRAM=-1;
-static int num_names=0;
-static name_struct *names = NULL;
+static BOOL needannounce=True;
-extern int Client;
+/* this is our name database */
+static struct name_record *namelist = NULL;
-#define NAMEVALID(i) names[i].valid
-#define ISGROUP(i) (names[i].isgroup)
+/* list of servers to be returned by NetServerEnum */
+static struct server_record *serverlist = NULL;
-void process(void);
+/* this is the domain list. For the moment we will assume that our
+ primary domain is the first one listed in this list */
+static struct domain_record *domainlist = NULL;
/* are we running as a daemon ? */
static BOOL is_daemon = False;
-/* machine comment */
-static pstring comment="";
+/* machine comment for host announcements */
+static pstring ServerComment="";
+
+static BOOL got_bcast = False;
+static BOOL got_myip = False;
+static BOOL got_nmask = False;
-/* die after this number of 10ths of seconds if no activity and not a daemon */
-static int idle_timeout = NMBD_INETD_TIMEOUT*1000;
+static BOOL updatedlists = False;
+static int updatecount=0;
-extern pstring user_socket_options;
+/* what server type are we currently */
+static int ServerType =
+SV_TYPE_WORKSTATION | SV_TYPE_SERVER | SV_TYPE_TIME_SOURCE |
+SV_TYPE_PRINTQ_SERVER | SV_TYPE_SERVER_UNIX | SV_TYPE_POTENTIAL_BROWSER;
-static void add_group_name(char *name);
-static void add_host_name(char *name,int type,struct in_addr *ip);
-static void dump_names(void);
+/* here are my election parameters */
+/* NTAS uses 2, NT uses 1, WfWg uses 0 */
+#define MAINTAIN_LIST 1
+#define ELECTION_VERSION 1
-static BOOL got_bcast = False;
-static BOOL got_myip = False;
-static BOOL got_nmask = False;
+static BOOL RunningElection = False;
+static BOOL needelection = False;
+static int ElectionCount = 0;
+static int StartupTime =0;
+/* WfWg uses 01040b01 */
+/* Win95 uses 01041501 */
+/* NTAS uses ?? */
+static uint32 ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
+
+/* we currently support being the master for just one group. Being the
+ master for more than one group might be tricky as NetServerEnum is
+ often asked for a list without naming the group */
+static fstring PrimaryGroup="";
+
+#define AM_MASTER (PrimaryGroup[0] && (ServerType & SV_TYPE_MASTER_BROWSER))
+
+#define MSBROWSE "\001\002__MSBROWSE__\002"
+
/****************************************************************************
catch a sighup
****************************************************************************/
@@ -101,10 +112,9 @@
{
BlockSignals(True);
- DEBUG(0,("Got SIGHUP - not implemented\n"));
+ DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
dump_names();
- if (!is_daemon)
- exit(1);
+ reload_services(True);
BlockSignals(False);
#ifndef DONT_REINSTALL_SIG
@@ -127,6 +137,43 @@
return(0);
}
+#if DUMP_CORE
+/*******************************************************************
+prepare to dump a core file - carefully!
+********************************************************************/
+static BOOL dump_core(void)
+{
+ char *p;
+ pstring dname;
+ strcpy(dname,debugf);
+ if ((p=strrchr(dname,'/'))) *p=0;
+ strcat(dname,"/corefiles");
+ mkdir(dname,0700);
+ chown(dname,getuid(),getgid());
+ chmod(dname,0700);
+ if (chdir(dname)) return(False);
+ umask(~(0700));
+
+#ifndef NO_GETRLIMIT
+#ifdef RLIMIT_CORE
+ {
+ struct rlimit rlp;
+ getrlimit(RLIMIT_CORE, &rlp);
+ rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
+ setrlimit(RLIMIT_CORE, &rlp);
+ getrlimit(RLIMIT_CORE, &rlp);
+ DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
+ }
+#endif
+#endif
+
+
+ DEBUG(0,("Dumping core in %s\n",dname));
+ return(True);
+}
+#endif
+
+
/****************************************************************************
possibly continue after a fault
****************************************************************************/
@@ -139,1536 +186,1585 @@
if (is_daemon && errcount<100)
process();
- exit(1);
+#if DUMP_CORE
+ if (dump_core()) return;
+#endif
+
+ return;
}
/****************************************************************************
true if two netbios names are equal
****************************************************************************/
-static BOOL name_equal(char *s1,char *s2,int type1,int type2)
+static BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2)
{
- char n1[20],n2[20];
+ if (n1->name_type != n2->name_type) return(False);
+
+ return(strequal(n1->name,n2->name) && strequal(n1->scope,n2->scope));
+}
- if (type1 != type2) return(False);
+/****************************************************************************
+ add a netbios name into the namelist
+ **************************************************************************/
+static void add_name(struct name_record *n)
+{
+ struct name_record *n2;
- StrnCpy(n1,s1,15);
- StrnCpy(n2,s2,15);
+ if (!namelist) {
+ namelist = n;
+ n->prev = NULL;
+ n->next = NULL;
+ return;
+ }
- trim_string(n1,NULL," ");
- trim_string(n2,NULL," ");
+ for (n2 = namelist; n2->next; n2 = n2->next) ;
- return(strequal(n1,n2));
+ n2->next = n;
+ n->next = NULL;
+ n->prev = n2;
}
/****************************************************************************
-add a netbios name
-****************************************************************************/
-static int add_name(void)
+ add a domain into the list
+ **************************************************************************/
+static void add_domain(struct domain_record *d)
{
- int i;
+ struct domain_record *d2;
- for (i=0;i<num_names;i++)
- if (!names[i].valid)
- break;
-
- if (i==num_names) {
- name_struct *n;
- if (num_names == 0)
- n = (name_struct *)malloc(sizeof(name_struct));
- else
- n = (name_struct *)realloc(names,sizeof(name_struct)*(num_names+1));
- if (!n) {
- DEBUG(0,("Can't malloc more names space!\n"));
- return(-1);
- }
- i = num_names;
- num_names++;
- names = n;
+ if (!domainlist) {
+ domainlist = d;
+ d->prev = NULL;
+ d->next = NULL;
+ return;
}
- bzero(&names[i],sizeof(names[i]));
+ for (d2 = domainlist; d2->next; d2 = d2->next) ;
- return(i);
+ d2->next = d;
+ d->next = NULL;
+ d->prev = d2;
}
+
/****************************************************************************
-find a name
-****************************************************************************/
-static int find_name(char *s,int type,BOOL groups)
+ add a server into the list
+ **************************************************************************/
+static void add_server(struct server_record *s)
{
- int i;
- time_t t = time(NULL);
+ struct server_record *s2;
- for (i=0;i<num_names;i++)
- if (names[i].valid && (groups || !ISGROUP(i)))
- {
- if ((names[i].ttl > 0) && (t > (names[i].start_time + names[i].ttl)))
- names[i].valid = False;
- else
- {
- if (name_equal(s,names[i].name,type,names[i].type)) {
- return(i);
- }
- }
- }
- return -1;
+ if (!serverlist) {
+ serverlist = s;
+ s->prev = NULL;
+ s->next = NULL;
+ return;
+ }
+
+ for (s2 = serverlist; s2->next; s2 = s2->next) ;
+
+ s2->next = s;
+ s->next = NULL;
+ s->prev = s2;
}
+/****************************************************************************
+ remove a name from the namelist. The pointer must be an element just
+ retrieved
+ **************************************************************************/
+static void remove_name(struct name_record *n)
+{
+ struct name_record *nlist = namelist;
+ while (nlist && nlist != n) nlist = nlist->next;
+ if (nlist) {
+ if (nlist->next) nlist->next->prev = nlist->prev;
+ if (nlist->prev) nlist->prev->next = nlist->next;
+ free(nlist);
+ }
+}
/****************************************************************************
-check names, and change any 0 IPs to myip
-****************************************************************************/
-static void check_names(void)
+ find a name in the namelist
+ **************************************************************************/
+static struct name_record *find_name(struct nmb_name *n)
{
- int i;
- int group_count=0;
+ struct name_record *ret;
+ for (ret = namelist; ret; ret = ret->next)
+ if (name_equal(&ret->name,n)) return(ret);
- /* add the magic __SAMBA__ name */
- add_host_name("__SAMBA__",0x20,&myip);
- add_host_name("__SAMBA__",0x0,&myip);
+ return(NULL);
+}
- for (i=0;i<num_names;i++)
- if (names[i].valid) {
- if (ISGROUP(i)) group_count++;
- }
+/****************************************************************************
+ dump a copy of the name table
+ **************************************************************************/
+static void dump_names(void)
+{
+ time_t t = time(NULL);
+ struct name_record *n;
+ struct domain_record *d;
- if (group_count == 0)
- add_group_name(WORKGROUP);
+ DEBUG(3,("Dump of local name table:\n"));
+ for (n = namelist; n; n = n->next) {
+ DEBUG(3,("%s %s TTL=%d Unique=%s\n",
+ namestr(&n->name),
+ inet_ntoa(n->ip),
+ n->death_time?n->death_time-t:0,
+ BOOLSTR(n->unique)));
+ }
- for (i=0;i<num_names;i++)
- if (names[i].valid && strequal((char *)inet_ntoa(names[i].ip),"0.0.0.0"))
- names[i].ip = (ISGROUP(i)?bcast_ip:myip);
+ DEBUG(3,("\nDump of domain list:\n"));
+ for (d = domainlist; d; d = d->next)
+ DEBUG(3,("%s %s\n",d->name,inet_ntoa(d->bcast_ip)));
}
/****************************************************************************
-dump a copy of the name table
-****************************************************************************/
-static void dump_names(void)
+ add a host entry to the name list
+ ****************************************************************************/
+static struct name_record *add_host_entry(char *name,int type,BOOL unique,int ttl,
+ enum name_source source,
+ struct in_addr ip)
{
- int i;
- DEBUG(3,("Dump of local name table\n"));
- for (i=0;i<num_names;i++)
- if (names[i].valid) {
- DEBUG(3,("%s %s %d %s",
- names[i].name,inet_ntoa(names[i].ip),
- names[i].ttl,BOOLSTR(names[i].isgroup)));
- if (names[i].found_master)
- DEBUG(3,(" %s",inet_ntoa(names[i].master_ip)));
- DEBUG(3,("\n"));
- }
+ struct name_record *n;
+ struct name_record *n2=NULL;
+
+ n = (struct name_record *)malloc(sizeof(*n));
+ if (!n) return(NULL);
+
+ bzero((char *)n,sizeof(*n));
+
+ make_nmb_name(&n->name,name,type,scope);
+ if ((n2=find_name(&n->name))) {
+ free(n);
+ n = n2;
+ }
+
+ if (ttl) n->death_time = time(NULL)+ttl*3;
+ n->ip = ip;
+ n->unique = unique;
+ n->source = source;
+
+ if (!n2) add_name(n);
+
+ DEBUG(3,("Added host entry %s at %s ttl=%d unique=%s\n",
+ namestr(&n->name),inet_ntoa(ip),ttl,BOOLSTR(unique)));
+
+ return(n);
}
/****************************************************************************
-load a netbios hosts file
-****************************************************************************/
-static void load_hosts_file(char *fname)
+ add a domain entry
+ ****************************************************************************/
+static struct domain_record *add_domain_entry(char *name,struct in_addr ip)
{
- int i;
- FILE *f = fopen(fname,"r");
- pstring line;
- if (!f)
- {
- DEBUG(2,("Not using non-existant lmhosts file %s\n",fname));
- return;
- }
+ struct domain_record *d;
- while (!feof(f))
- {
- if (!fgets_slash(line,sizeof(pstring),f)) continue;
-
- if (*line == '#') continue;
+ d = (struct domain_record *)malloc(sizeof(*d));
- {
- string ip="",name="",flags="",extra="";
- unsigned long a;
- char *ptr;
- int count = 0;
- ptr = line;
- if (next_token(&ptr,ip,NULL)) ++count;
- if (next_token(&ptr,name,NULL)) ++count;
- if (next_token(&ptr,flags,NULL)) ++count;
- if (next_token(&ptr,extra,NULL)) ++count;
+ if (!d) return(NULL);
- if (count <= 0) continue;
+ bzero((char *)d,sizeof(*d));
- if (count > 0 && count < 2)
- {
- DEBUG(0,("Ill formed hosts line [%s]\n",line));
- continue;
- }
+ StrnCpy(d->name,name,sizeof(d->name)-1);
+ d->bcast_ip = ip;
- i = add_name();
- if (i < 0)
- {
- fclose(f);
- return;
- }
+ if (!*PrimaryGroup && ip_equal(bcast_ip,ip) && name[0] != '*') {
+ strcpy(PrimaryGroup,name);
+ strupper(PrimaryGroup);
+ }
- a = interpret_addr(ip);
- putip((char *)&names[i].ip,(char *)&a);
+ add_domain(d);
- names[i].valid = True;
- names[i].source = LMHOSTS;
+ ip = *interpret_addr2("255.255.255.255");
+ if (name[0] != '*') add_host_entry(name,0x1e,False,0,SELF,ip);
- StrnCpy(names[i].name,name,15);
- if (strchr(flags,'G') || strchr(flags,'S'))
- names[i].isgroup = True;
- if (strchr(flags,'M') && !ISGROUP(i))
- strcpy(myname,name);
- if (strchr(flags,'U'))
- names[i].unicast = True;
- if (names[i].isgroup)
- names[i].type = 0xF0; /* hopefully invalid */
- else
- names[i].type = 0x20;
- }
- }
+ DEBUG(3,("Added domain entry %s at %s\n",
+ name,inet_ntoa(ip)));
- fclose(f);
+ return(d);
}
-
/****************************************************************************
-add a netbios group name
-****************************************************************************/
-static void add_group_name(char *name)
+ add a server entry
+ ****************************************************************************/
+static struct server_record *add_server_entry(char *name,int servertype,
+ int ttl,char *comment)
{
- int i = add_name();
- if (i < 0)
- return;
+ BOOL newentry=False;
+ struct server_record *s;
+
+ updatedlists=True;
+
+ for (s = serverlist; s; s = s->next)
+ if (strequal(name,s->name)) break;
+
+ if (!s) {
+ newentry = True;
+ s = (struct server_record *)malloc(sizeof(*s));
+
+ if (!s) return(NULL);
+
+ bzero((char *)s,sizeof(*s));
+ }
+
+ /* update the entry */
+ StrnCpy(s->name,name,sizeof(s->name)-1);
+ StrnCpy(s->comment,comment,sizeof(s->comment)-1);
+ s->servertype = servertype;
+ s->death_time = ttl?time(NULL)+ttl*3:0;
+ strupper(s->name);
+ if (s->servertype & SV_TYPE_DOMAIN_ENUM) strupper(s->comment);
+
+ if (!newentry) return(s);
- bzero((char *)&names[i].ip,sizeof(names[i].ip));
+ add_server(s);
- strcpy(names[i].name,name);
- names[i].isgroup = True;
- names[i].valid = True;
- names[i].type = 0xF0;
- names[i].source = SELF;
+ DEBUG(3,("Added server entry %s of type %x (%s)\n",
+ name,servertype,comment));
+
+ return(s);
}
+
/****************************************************************************
-add a host name
-****************************************************************************/
-static void add_host_name(char *name,int type,struct in_addr *ip)
+ add the magic samba names, useful for finding samba servers
+ **************************************************************************/
+static void add_my_names(void)
{
- int i;
+ struct in_addr ip = *interpret_addr2("0.0.0.0");
- if (find_name(name,type,True) >= 0) return;
+ add_host_entry("__SAMBA__",0x20,True,0,SELF,ip);
+ add_host_entry("__SAMBA__",0x0,True,0,SELF,ip);
+ add_host_entry(myname,0x20,True,0,SELF,ip);
+ add_host_entry(myname,0x0,True,0,SELF,ip);
+ add_host_entry(myname,0x1f,True,0,SELF,ip); /* used for chat, I think */
+ if (!domainlist)
+ add_domain_entry(lp_workgroup(),bcast_ip);
+ add_server_entry(myname,
+ ServerType,
+ 0,ServerComment);
+}
- i = add_name();
- if (i < 0)
- return;
- names[i].ip = *ip;
- strcpy(names[i].name,name);
- names[i].valid = True;
- names[i].start_time = time(NULL);
- names[i].ttl = 0;
- names[i].type = type;
- names[i].source = SELF;
+/*******************************************************************
+ write out browse.dat
+ ******************************************************************/
+static void write_browse_list(void)
+{
+ struct server_record *s;
+ pstring fname,fnamenew;
+ FILE *f;
+
+ updatecount++;
+
+ strcpy(fname,lp_lockdir());
+ trim_string(fname,NULL,"/");
+ strcat(fname,"/");
+ strcat(fname,SERVER_LIST);
+ strcpy(fnamenew,fname);
+ strcat(fnamenew,".");
+
+ f = fopen(fnamenew,"w");
+
+ if (!f) {
+ DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
+ return;
+ }
+
+ for (s=serverlist; s ; s = s->next) {
+ /* don't list domains I don't have a master for */
+ if ((s->servertype & SV_TYPE_DOMAIN_ENUM) && !s->comment[0]) continue;
+
+ fprintf(f,"\"%s\"\t%08x\t\"%s\"\n",s->name,s->servertype,s->comment);
+ }
+
+
+ fclose(f);
+ unlink(fname);
+ rename(fnamenew,fname);
+ DEBUG(3,("Wrote browse list %s\n",fname));
}
-/****************************************************************************
-word out the length of a nmb message
-****************************************************************************/
-static int nmb_len(char *buf)
+/*******************************************************************
+ expire old names in the namelist and serverlist
+ ******************************************************************/
+static void expire_names(void)
{
-int i;
-int ret = 12;
-char *p = buf;
-int qdcount = RSVAL(buf,4);
-int ancount = RSVAL(buf,6);
-int nscount = RSVAL(buf,8);
-int arcount = RSVAL(buf,10);
+ static time_t lastrun=0;
+ time_t t = time(NULL);
+ struct name_record *n;
+ struct name_record *next;
+ struct server_record *s;
+ struct server_record *nexts;
+
+ if (!lastrun) lastrun = t;
+ if (t < lastrun + 5) return;
+ lastrun = t;
+
+ /* expire old names */
+ for (n = namelist; n; n = next) {
+ if (n->death_time && n->death_time < t) {
+ DEBUG(3,("Removing dead name %s\n",
+ namestr(&n->name)));
+ next = n->next;
+ if (n->prev) n->prev->next = n->next;
+ if (n->next) n->next->prev = n->prev;
+ if (namelist == n) namelist = n->next;
+ free(n);
+ } else {
+ next = n->next;
+ }
+ }
-/* check for insane qdcount values? */
-if (qdcount > 100 || qdcount < 0)
- {
- DEBUG(6,("Invalid qdcount? qdcount=%d\n",qdcount));
- return(0);
+ /* expire old entries in the serverlist */
+ for (s = serverlist; s; s = nexts) {
+ if (s->death_time && s->death_time < t) {
+ DEBUG(3,("Removing dead server %s\n",s->name));
+ updatedlists = True;
+ nexts = s->next;
+ if (s->prev) s->prev->next = s->next;
+ if (s->next) s->next->prev = s->prev;
+ if (serverlist == s) serverlist = s->next;
+ free(s);
+ } else {
+ nexts = s->next;
+ }
}
+}
-for (i=0;i<qdcount;i++)
- {
- p = buf + ret;
- ret += name_len(p) + 4;
+
+/*******************************************************************
+ delete old names from the namelist
+ ******************************************************************/
+static void housekeeping(void)
+{
+ time_t t = time(NULL);
+
+ expire_names();
+
+ /* write out the browse.dat database for smbd to get */
+ if (updatedlists) {
+ write_browse_list();
+ updatedlists = False;
}
-for (i=0;i<(ancount + nscount + arcount);i++)
{
- int rdlength;
- p = buf + ret;
- ret += name_len(p) + 8;
- p = buf + ret;
- rdlength = RSVAL(p,0);
- ret += rdlength + 2;
+ /* occasionally check to see if the master browser is around */
+ static time_t lastrun=0;
+ if (!lastrun) lastrun = t;
+ if (t < lastrun + 5*60) return;
+ lastrun = t;
+
+ if (!AM_MASTER && *PrimaryGroup &&
+ !name_query(ClientNMB,PrimaryGroup,0x1d,True,False,
+ bcast_ip,NULL,queue_packet)) {
+ DEBUG(2,("Forcing election on %s\n",PrimaryGroup));
+ needelection = True;
+ }
}
-
-return(ret);
}
+
/****************************************************************************
-receive a name message. timeout is in milliseconds
-****************************************************************************/
-static int receive_nmb(char *buffer,int timeout)
+ reload the services file
+ **************************************************************************/
+BOOL reload_services(BOOL test)
{
- int ret = read_max_udp(Client,buffer,sizeof(pstring),timeout);
+ BOOL ret;
+ extern fstring remote_machine;
+
+ strcpy(remote_machine,"nmbd");
- if (ret < 0)
+ if (lp_loaded())
{
- DEBUG(0,("No bytes from client\n"));
- if (!is_daemon)
+ pstring fname;
+ strcpy(fname,lp_configfile());
+ if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
{
- close_sockets();
- exit(0);
+ strcpy(servicesf,fname);
+ test = False;
}
}
-
- if (ret <= 1)
- return 0;
- log_in(buffer,ret);
+ if (test && !lp_file_list_changed())
+ return(True);
- DEBUG(3,("received packet from (%s) nmb_len=%d len=%d\n",
- inet_ntoa(lastip),nmb_len(buffer),ret));
+ ret = lp_load(servicesf,True);
- num_good_receives++;
+ /* perhaps the config filename is now set */
+ if (!test)
+ reload_services(True);
return(ret);
}
+
+
/****************************************************************************
-send a name message
+load a netbios hosts file
****************************************************************************/
-static BOOL send_nmb(char *buf, int len, struct in_addr *ip,int port)
+static void load_hosts_file(char *fname)
{
- BOOL ret;
- struct sockaddr_in sock_out;
+ FILE *f = fopen(fname,"r");
+ pstring line;
+ if (!f) {
+ DEBUG(2,("Can't open lmhosts file %s\n",fname));
+ return;
+ }
- /* set the address and port */
- bzero((char *)&sock_out,sizeof(sock_out));
- putip((char *)&sock_out.sin_addr,(char *)ip);
- sock_out.sin_port = htons( port );
- sock_out.sin_family = AF_INET;
-
- /* log the packet */
- log_out(buf,len);
-
- if (DEBUGLEVEL > 0)
- DEBUG(3,("sending a packet of len %d to (%s) on port 137 of type DGRAM\n",
- len,inet_ntoa(*ip)));
-
- /* send it */
- ret = (sendto(Client,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
+ while (!feof(f))
+ {
+ if (!fgets_slash(line,sizeof(pstring),f)) continue;
+
+ if (*line == '#') continue;
- if (!ret)
- DEBUG(0,("Send packet failed. ERRNO=%d\n",errno));
+ {
+ BOOL group=False;
+ string ip="",name="",flags="",extra="";
+ char *ptr;
+ int count = 0;
+ struct in_addr ipaddr;
+ enum name_source source = LMHOSTS;
- if (ret)
- num_good_sends++;
+ ptr = line;
- return(ret);
-}
+ if (next_token(&ptr,ip,NULL)) ++count;
+ if (next_token(&ptr,name,NULL)) ++count;
+ if (next_token(&ptr,flags,NULL)) ++count;
+ if (next_token(&ptr,extra,NULL)) ++count;
-/*******************************************************************
-check if an IP is on my net
-********************************************************************/
-static BOOL is_mynet(struct in_addr ip)
-{
- unsigned int net1,net2,nmask,subnet1,subnet2;
+ if (count <= 0) continue;
- nmask = *(unsigned int *)&Netmask;
- net1 = (*(unsigned int *)&myip);
- subnet1 = net1 & nmask;
- net2 = (*(unsigned int *)&ip);
- subnet2 = net2 & nmask;
-
- return((net1 != net2) && (subnet1 == subnet2));
-}
+ if (count > 0 && count < 2)
+ {
+ DEBUG(0,("Ill formed hosts line [%s]\n",line));
+ continue;
+ }
-/****************************************************************************
-interpret a node status response
-****************************************************************************/
-static void interpret_node_status(char *inbuf, char *master)
-{
- int level = master?3:0;
- char *p = inbuf + 12 + name_len(inbuf+12) + 10;
- int numnames = CVAL(p,0);
- DEBUG(level,("received %d names\n",numnames));
+ if (strchr(flags,'G') || strchr(flags,'S'))
+ group = True;
- p += 1;
- while (numnames--)
- {
- char qname[17];
- int type;
- fstring flags="";
- StrnCpy(qname,p,15);
- type = CVAL(p,15);
- p += 16;
-
- if (p[0] & 0x80) strcat(flags,"<GROUP> ");
- if (p[0] & 0x60 == 0) strcat(flags,"B ");
- if (p[0] & 0x60 == 1) strcat(flags,"P ");
- if (p[0] & 0x60 == 2) strcat(flags,"M ");
- if (p[0] & 0x60 == 3) strcat(flags,"_ ");
- if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
- if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
- if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
- if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
+ if (strchr(flags,'M') && !group) {
+ source = SELF;
+ strcpy(myname,name);
+ }
+
+ ipaddr = *interpret_addr2(ip);
- if (master && type == 0x1d) {
- StrnCpy(master,qname,15);
+ if (group) {
+ add_domain_entry(name,ipaddr);
+ } else {
+ add_host_entry(name,0x20,True,0,source,ipaddr);
+ }
}
-
- DEBUG(level,("\t%s (type=0x%x)\t%s\n",qname,type,flags));
- p+=2;
}
- DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
- IVAL(p,20),IVAL(p,24)));
+
+ fclose(f);
}
+/*******************************************************************
+ check if 2 IPs are on the same net
+ we will assume the local netmask, although this could be wrong XXXX
+ ******************************************************************/
+static BOOL same_net(struct in_addr ip1,struct in_addr ip2)
+{
+ unsigned long net1,net2,nmask;
+
+ nmask = ntohl(Netmask.s_addr);
+ net1 = ntohl(ip1.s_addr);
+ net2 = ntohl(ip2.s_addr);
+
+ return((net1 & nmask) == (net2 & nmask));
+}
/****************************************************************************
-show a nmb message
-****************************************************************************/
-static void show_nmb(char *inbuf)
+ send an election packet
+ **************************************************************************/
+static void send_election(char *group,uint32 criterion,int timeup,char *name)
{
- int i,l;
- int name_trn_id = RSVAL(inbuf,0);
- int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
- int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
- int rcode = CVAL(inbuf,3) & 0xF;
- int qdcount = RSVAL(inbuf,4);
- int ancount = RSVAL(inbuf,6);
- int nscount = RSVAL(inbuf,8);
- int arcount = RSVAL(inbuf,10);
- char name[100];
+ pstring outbuf;
+ char *p;
- if (DEBUGLEVEL < 3) return;
+ DEBUG(2,("Sending election to %s for workgroup %s\n",
+ inet_ntoa(bcast_ip),group));
- DEBUG(3,("\nPACKET INTERPRETATION\n"));
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+ CVAL(p,0) = 8; /* election */
+ p++;
- if (opcode == 5 && ((nm_flags & ~1) == 0x10) && rcode == 0)
- DEBUG(3,("NAME REGISTRATION REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+ CVAL(p,0) = ELECTION_VERSION;
+ SIVAL(p,1,criterion);
+ SIVAL(p,5,timeup*1000); /* ms - despite the spec */
+ p += 13;
+ strcpy(p,name);
+ strupper(p);
+ p = skip_string(p,1);
- if (opcode == 5 && ((nm_flags & ~1) == 0x00) && rcode == 0)
- DEBUG(3,("NAME OVERWRITE REQUEST AND DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
-
- if (opcode == 9 && ((nm_flags & ~1) == 0x00) && rcode == 0)
- DEBUG(3,("NAME REFRESH REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+ send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ name,group,0,0x1e,bcast_ip,myip);
+}
- if (opcode == 8)
- DEBUG(3,("NAME REFRESH (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
-
- if (opcode == 5 && nm_flags == 0x58 && rcode == 0)
- DEBUG(3,("POSITIVE NAME REGISTRATION RESPONSE\n"));
-
- if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode != 7)
- DEBUG(3,("NEGATIVE NAME REGISTRATION RESPONSE\n"));
-
- if (opcode == 5 && nm_flags == 0x50 && rcode == 0)
- DEBUG(3,("END-NODE CHALLENGE REGISTRATION RESPONSE\n"));
-
- if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode == 7)
- DEBUG(3,("NAME CONFLICT DEMAND\n"));
-
- if (opcode == 6 && (nm_flags&~1) == 0x00 && rcode == 0)
- DEBUG(3,("NAME RELEASE REQUEST & DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
-
- if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode == 0)
- DEBUG(3,("POSITIVE NAME RELEASE RESPONSE\n"));
-
- if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode != 0)
- DEBUG(3,("NEGATIVE NAME RELEASE RESPONSE\n"));
-
- if (opcode == 0 && (nm_flags&~1) == 0x10 && rcode == 0)
- DEBUG(3,("NAME QUERY REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
-
- if (opcode == 0 && (nm_flags&~0x28) == 0x50 && rcode == 0)
- DEBUG(3,("POSITIVE NAME QUERY RESPONSE\n"));
-
- if (opcode == 0 && (nm_flags&~0x08) == 0x50 && rcode != 0)
- DEBUG(3,("NEGATIVE NAME QUERY RESPONSE\n"));
-
- if (opcode == 0 && nm_flags == 0x10 && rcode == 0)
- DEBUG(3,("REDIRECT NAME QUERY RESPONSE\n"));
- if (opcode == 7 && nm_flags == 0x80 && rcode == 0)
- DEBUG(3,("WAIT FOR ACKNOWLEDGEMENT RESPONSE\n"));
-
- if (opcode == 0 && (nm_flags&~1) == 0x00 && rcode == 0)
- DEBUG(3,("NODE STATUS REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+/****************************************************************************
+ send a backup list response
+ **************************************************************************/
+static void send_backup_list(char *name,int token,struct nmb_name *to,
+ struct in_addr ip)
+{
+ pstring outbuf;
+ char *p;
- if (opcode == 0 && nm_flags == 0x40 && rcode == 0)
- {
- DEBUG(3,("NODE STATUS RESPONSE\n"));
- interpret_node_status(inbuf,NULL);
- }
-
-
- DEBUG(3,("name_trn_id=0x%x\nopcode=0x%x\nnm_flags=0x%x\nrcode=0x%x\n",
- name_trn_id,opcode,nm_flags,rcode));
- DEBUG(3,("qdcount=%d\nancount=%d\nnscount=%d\narcount=%d\n",
- qdcount,ancount,nscount,arcount));
+ DEBUG(2,("Sending backup list to %s for workgroup %s\n",
+ inet_ntoa(ip),PrimaryGroup));
- l = 12;
- for (i=0;i<qdcount;i++)
- {
- int type,class;
- DEBUG(3,("QUESTION %d\n",i));
- name_extract(inbuf,l,name);
- l += name_len(inbuf+l);
- type = RSVAL(inbuf+l,0);
- class = RSVAL(inbuf+l,2);
- l += 4;
- DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
- }
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+ CVAL(p,0) = 10; /* backup list response */
+ p++;
- for (i=0;i<(ancount + nscount + arcount);i++)
- {
- int type,class,ttl,rdlength;
- DEBUG(3,("RESOURCE %d\n",i));
- name_extract(inbuf,l,name);
- l += name_len(inbuf + l);
- type = RSVAL(inbuf+l,0);
- class = RSVAL(inbuf+l,2);
- ttl = RIVAL(inbuf+l,4);
- rdlength = RSVAL(inbuf+l,8);
- l += 10 + rdlength;
- DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
- DEBUG(3,("\tttl=%d\n\trdlength=%d\n",ttl,rdlength));
- }
+ CVAL(p,0) = 1; /* count */
+ SIVAL(p,1,token);
+ p += 5;
+ strcpy(p,name);
+ strupper(p);
+ p = skip_string(p,1) + 1;
- DEBUG(3,("\n"));
-
+ send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ myname,to->name,0,to->name_type,ip,myip);
}
-/****************************************************************************
-do a netbios name query to find someones IP
-****************************************************************************/
-static BOOL name_query(char *name, char name_type, BOOL bcast,
- struct in_addr to_ip, struct in_addr *ip, void (*fn)())
+/*******************************************************************
+ become the master browser
+ ******************************************************************/
+static void become_master(void)
{
- BOOL found=False;
- pstring inbuf,outbuf;
- static uint16 name_trn_id = 0x6242;
- char *p;
- int retries = 3;
- int retry_time = bcast?250:5000;
- struct timeval tval;
-
- bzero(inbuf,sizeof(inbuf));
- bzero(outbuf,sizeof(outbuf));
-
- name_trn_id += getpid() % 100;
- name_trn_id = (name_trn_id % 0x7FFF);
+ DEBUG(2,("Becoming master for %s\n",PrimaryGroup));
- RSSVAL(outbuf,0,name_trn_id);
- CVAL(outbuf,2) = 0x1;
- CVAL(outbuf,3) = bcast?(1<<4):0;
- RSSVAL(outbuf,4,1);
- RSSVAL(outbuf,6,0);
- RSSVAL(outbuf,8,0);
- RSSVAL(outbuf,10,0);
- p = outbuf+12;
- name_mangle(name,p,name_type);
- p += name_len(p);
- RSSVAL(p,0,0x20);
- RSSVAL(p,2,0x1);
- p += 4;
-
- DEBUG(2,("Sending name query for %s\n",name));
-
- show_nmb(outbuf);
-
- GetTimeOfDay(&tval);
-
- if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
- return False;
- retries--;
+ ServerType |= SV_TYPE_MASTER_BROWSER;
+ ServerType |= SV_TYPE_BACKUP_BROWSER;
+ ElectionCriterion |= 0x5;
- while (1)
- {
- struct timeval tval2;
- GetTimeOfDay(&tval2);
- if (TvalDiff(&tval,&tval2) > retry_time) {
- if (!retries) break;
- if (!found && !send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
- return False;
- GetTimeOfDay(&tval);
- retries--;
- }
+ add_host_entry(PrimaryGroup,0x1d,True,0,SELF,myip);
+ add_host_entry(PrimaryGroup,0x0,False,0,SELF,myip);
+ add_host_entry(MSBROWSE,1,False,0,SELF,myip);
+ add_server_entry(PrimaryGroup,SV_TYPE_DOMAIN_ENUM,0,myname);
+ add_server_entry(myname,ServerType,0,ServerComment);
- if (receive_nmb(inbuf,90))
- {
- int rec_name_trn_id = RSVAL(inbuf,0);
- int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
- int rcode = CVAL(inbuf,3) & 0xF;
- int response = (CVAL(inbuf,2)>>7);
- int qdcount = RSVAL(inbuf,4);
- int ancount = RSVAL(inbuf,6);
- show_nmb(inbuf);
-
- /* is it a positive response to our request? */
- if ((rec_name_trn_id == name_trn_id) && response) {
- if (opcode == 0 && qdcount==0 && ancount==1 && rcode == 0) {
- putip((char *)ip,inbuf + 12 + name_len(inbuf+12) + 12);
- DEBUG(2,("Got a positive name query response from %s",
- inet_ntoa(lastip)));
- DEBUG(2,(" (%s)\n",inet_ntoa(*ip)));
- found=True; retries=0;
- continue;
- } else {
- /* some other sort of response, yuck */
- DEBUG(2,("Unknown response\n"));
- continue;
- }
- } else {
- if (fn) fn(inbuf);
- }
- }
- }
+ announce_request(PrimaryGroup);
- return(found);
+ needannounce = True;
}
-/****************************************************************************
-do a netbios name status to a host
-****************************************************************************/
-static BOOL name_status(char *name,int type,struct in_addr to_ip,void (*fn)(),
- char *master)
+
+/*******************************************************************
+ unbecome the master browser
+ ******************************************************************/
+static void become_nonmaster(void)
{
- pstring inbuf,outbuf;
- static uint16 name_trn_id = 0x4262;
- char *p;
- int retries = 3;
- int retry_time = 5000;
- struct timeval tval;
+ struct name_record *n;
+ struct nmb_name nn;
- bzero(inbuf,sizeof(inbuf));
- bzero(outbuf,sizeof(outbuf));
+ DEBUG(2,("Becoming non-master for %s\n",PrimaryGroup));
+
+ ServerType &= ~SV_TYPE_MASTER_BROWSER;
+ ElectionCriterion &= ~0x4;
- if (!fn)
- DEBUG(1,("Querying status of name %s\n",name));
+ make_nmb_name(&nn,PrimaryGroup,0x1d,scope);
+ n = find_name(&nn);
+ if (n && n->source == SELF) remove_name(n);
- name_trn_id += getpid() % 100;
- name_trn_id = (name_trn_id % 10000);
+ make_nmb_name(&nn,MSBROWSE,1,scope);
+ n = find_name(&nn);
+ if (n && n->source == SELF) remove_name(n);
+}
- RSSVAL(outbuf,0,name_trn_id);
- CVAL(outbuf,2) = 0;
- CVAL(outbuf,3) = 0x0;
- RSSVAL(outbuf,4,1);
- RSSVAL(outbuf,6,0);
- RSSVAL(outbuf,8,0);
- RSSVAL(outbuf,10,0);
- p = outbuf+12;
- name_mangle(name,p,type);
- p += name_len(p);
- RSSVAL(p,0,0x21);
- RSSVAL(p,2,0x1);
- p += 4;
-
- DEBUG(fn?3:2,("Sending name status query for %s\n",name));
- show_nmb(outbuf);
+/*******************************************************************
+ run the election
+ ******************************************************************/
+static void run_election(void)
+{
+ time_t t = time(NULL);
+ static time_t lastime = 0;
- GetTimeOfDay(&tval);
+ if (!*PrimaryGroup || !RunningElection) return;
- if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
- return False;
-
- while (1)
- {
- struct timeval tval2;
- GetTimeOfDay(&tval2);
- if (TvalDiff(&tval,&tval2) > retry_time) {
- if (!retries) break;
- if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
- return False;
- GetTimeOfDay(&tval);
- retries--;
- }
-
- if (receive_nmb(inbuf,90))
- {
- int rec_name_trn_id = RSVAL(inbuf,0);
- int rcode = CVAL(inbuf,3) & 0xF;
- int response = (CVAL(inbuf,2)>>7);
- int qdcount = RSVAL(inbuf,4);
- int ancount = RSVAL(inbuf,6);
-
- show_nmb(inbuf);
-
- /* is it a positive response to our request? */
- if (response && (rec_name_trn_id == name_trn_id)) {
- if (rcode==0 && ancount==1 && qdcount==0) {
- DEBUG(fn?3:0,("Got a positive node status response from %s\n",
- inet_ntoa(lastip)));
- interpret_node_status(inbuf, master);
- return(True);
- }
- return(False);
- }
- if (fn) fn(inbuf);
- }
- }
+ /* send election packets once a second */
+ if (lastime &&
+ t-lastime <= 0) return;
- DEBUG(0,("No response (this is not unusual)\n"));
+ lastime = t;
- return(False);
+ send_election(PrimaryGroup,ElectionCriterion,t-StartupTime,myname);
+
+ if (ElectionCount++ < 4) return;
+
+ /* I won! now what :-) */
+ RunningElection = False;
+ DEBUG(2,(">>> Won election on %s <<<\n",PrimaryGroup));
+ become_master();
}
/****************************************************************************
-reply to a reg request
-****************************************************************************/
-static void reply_name_reg(char *inbuf)
+ construct a host announcement unicast
+ **************************************************************************/
+static void announce_host(struct domain_record *d,char *my_name,char *comment)
{
+ time_t t = time(NULL);
pstring outbuf;
- int rec_name_trn_id = RSVAL(inbuf,0);
- char qname[100]="";
- int ttl;
- char *p = inbuf;
- struct in_addr ip;
- int n=0;
- int name_type;
- unsigned char nb_flags;
- int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
- int bcast = (nm_flags&1);
- struct in_addr tmpip;
-
- bzero(outbuf,sizeof(outbuf));
+ char *p;
+ char *namep;
+ char *stypep;
+ char *commentp;
+
+ if (needannounce) {
+ /* drop back to a max 3 minute announce - this is to prevent a
+ single lost packet from stuffing things up for too long */
+ d->announce_interval = MIN(d->announce_interval,3*60);
+ d->lastannounce_time = t - (d->announce_interval+1);
+ }
- name_type = name_extract(inbuf,12,qname);
+ /* announce every minute at first then progress to every 12 mins */
+ if (d->lastannounce_time &&
+ (t - d->lastannounce_time) < d->announce_interval)
+ return;
- p += 12;
- p += name_len(p);
- p += 4;
- p += name_len(p);
- p += 4;
- ttl = RIVAL(p,0);
- nb_flags = CVAL(p,6);
- p += 8;
- putip((char *)&ip,p);
-
- DEBUG(2,("Name registration request for %s (%s) nb_flags=0x%x ntype=%d\n",
- qname,inet_ntoa(ip),nb_flags,name_type));
-
- if ((nb_flags&0x80) == 0 && (name_type != 0x1d)) {
- if (ttl==0) ttl = NMBD_MAX_TTL;
- ttl = MIN(ttl,NMBD_MAX_TTL);
+ if (d->announce_interval < 12*60) d->announce_interval += 60;
+ d->lastannounce_time = t;
- n = find_name(qname,name_type,True);
+ DEBUG(2,("Sending announcement to %s for workgroup %s type=%d\n",
+ inet_ntoa(d->bcast_ip),d->name));
- if (n>=0 && names[n].source != REGISTER && names[n].source != DNS)
- return;
+ if (!*comment) comment = "NoComment";
+ if (!*my_name) my_name = "NoName";
- if (n<0)
- n = add_name();
- if (n<0) return;
-
- bzero(&names[n],sizeof(names[n]));
-
- StrnCpy(names[n].name,qname,15);
- names[n].type = name_type;
- names[n].unicast = !dns_serve || is_mynet(ip);
- names[n].ip = ip;
- names[n].valid = True;
- names[n].ttl = ttl;
- names[n].source = REGISTER;
- names[n].start_time = time(NULL);
- DEBUG(2,("Added %s with ttl %d as (%s) (uni=%s)\n",
- qname,names[n].ttl,inet_ntoa(ip),BOOLSTR(names[n].unicast)));
- }
+ if (strlen(comment) > 43) comment[43] = 0;
- if (bcast) return;
+ bzero(outbuf,sizeof(outbuf));
+ CVAL(outbuf,0) = 1; /* host announce */
+ p = outbuf+1;
- /* Send a POSITIVE NAME REGISTRATION RESPONSE */
- RSSVAL(outbuf,0,rec_name_trn_id);
- CVAL(outbuf,2) = (1<<7) | (5<<3) | 5;
- CVAL(outbuf,3) = (1<<7);
- RSSVAL(outbuf,4,0);
- RSSVAL(outbuf,6,1);
- RSSVAL(outbuf,8,0);
- RSSVAL(outbuf,10,0);
- p = outbuf+12;
- strcpy(p,inbuf+12);
- p += name_len(p);
- RSSVAL(p,0,0x20);
- RSSVAL(p,2,0x1);
- /* we want them to refresh in case we die */
- if (!ttl) ttl = 15*60;
- ttl = MIN(ttl,15*60);
- RSIVAL(p,4,ttl);
-
- RSSVAL(p,8,6);
- RSSVAL(p,10,nb_flags);
- p += 12;
- putip(p,&ip);
- p += 4;
-
- DEBUG(2,("Sending a positive registration response\n"));
- if (DEBUGLEVEL > 2)
- show_nmb(outbuf);
-
- tmpip = lastip;
- num_good_sends++;
- send_nmb(outbuf,PTR_DIFF(p,outbuf),&tmpip,lastport>0?lastport:137);
+ CVAL(p,0) = updatecount;
+ SIVAL(p,1,d->announce_interval*1000); /* ms - despite the spec */
+ namep = p+5;
+ StrnCpy(p+5,my_name,16);
+ strupper(p+5);
+ CVAL(p,21) = 2; /* major version */
+ CVAL(p,22) = 0; /* minor version */
+ stypep = p+23;
+ SIVAL(p,23,ServerType);
+ SSVAL(p,27,0xaa55); /* browse signature */
+ SSVAL(p,29,1); /* browse version */
+ commentp = p+31;
+ strcpy(p+31,comment);
+ p += 31;
+ p = skip_string(p,1);
+
+ send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ my_name,d->name,0,0x1d,d->bcast_ip,myip);
+
+ /* if I'm the master then I also need to do a local master and
+ domain announcement */
+
+ if (AM_MASTER &&
+ strequal(d->name,PrimaryGroup) &&
+ ip_equal(bcast_ip,d->bcast_ip)) {
+
+ /* do master announcements as well */
+
+ CVAL(outbuf,0) = 15; /* local master announce */
+ send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ my_name,PrimaryGroup,0,0x1e,d->bcast_ip,myip);
+
+ CVAL(outbuf,0) = 12; /* domain announce */
+ StrnCpy(namep,PrimaryGroup,15);
+ strupper(namep);
+ StrnCpy(commentp,myname,15);
+ strupper(commentp);
+ SIVAL(stypep,0,(unsigned)0x80000000);
+ p = commentp + strlen(commentp) + 1;
- return;
+ send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ my_name,MSBROWSE,0,1,d->bcast_ip,myip);
+ }
}
+
/****************************************************************************
-reply to a name release
-****************************************************************************/
-static void reply_name_release(char *inbuf)
+ send a announce request to the local net
+ **************************************************************************/
+static void announce_request(char *group)
{
pstring outbuf;
- int rec_name_trn_id = RSVAL(inbuf,0);
- char qname[100]="";
- char *p = inbuf;
- struct in_addr ip;
- int n=0;
- int name_type;
- unsigned char nb_flags;
- struct in_addr tmpip;
- BOOL release_ok=False;
- int reason=5;
+ char *p;
+ DEBUG(2,("Sending announce request to %s for workgroup %s\n",
+ inet_ntoa(bcast_ip),group));
bzero(outbuf,sizeof(outbuf));
-
- name_type = name_extract(inbuf,12,qname);
+ p = outbuf;
+ CVAL(p,0) = 2; /* announce request */
+ p++;
- p += 12;
- p += name_len(p);
- p += 4;
- p += name_len(p);
- p += 4;
- nb_flags = CVAL(p,6);
- p += 8;
- putip((char *)&ip,p);
-
- DEBUG(2,("Name release request for %s (%s) nb_flags=0x%x ntype=%d\n",
- qname,inet_ntoa(ip),nb_flags,name_type));
-
- n = find_name(qname,name_type,True);
- if (n>=0 && names[n].source == REGISTER &&
- !memcmp((char *)&ip,(char *)&names[n].ip,sizeof(ip))) {
- release_ok = True;
- names[n].valid = False;
- }
-
- /* Send a POSITIVE NAME RELEASE RESPONSE */
- RSSVAL(outbuf,0,rec_name_trn_id);
- CVAL(outbuf,2) = (1<<7) | (6<<3) | 4;
- CVAL(outbuf,3) = release_ok?0:reason;
- RSSVAL(outbuf,4,0);
- RSSVAL(outbuf,6,1);
- RSSVAL(outbuf,8,0);
- RSSVAL(outbuf,10,0);
- p = outbuf+12;
- strcpy(p,inbuf+12);
- p += name_len(p);
- RSSVAL(p,0,0x20);
- RSSVAL(p,2,0x1);
- RSIVAL(p,4,0); /* ttl */
- RSSVAL(p,8,6);
- RSSVAL(p,10,nb_flags);
- p += 12;
- putip(p,&ip);
- p += 4;
-
- DEBUG(2,("Sending a %s name release response\n",release_ok?"positive":"negative"));
- if (DEBUGLEVEL > 2)
- show_nmb(outbuf);
-
- tmpip = lastip;
- num_good_sends++;
- send_nmb(outbuf,PTR_DIFF(p,outbuf),&tmpip,lastport>0?lastport:137);
+ CVAL(p,0) = 0; /* flags?? */
+ p++;
+ StrnCpy(p,myname,16);
+ strupper(p);
+ p = skip_string(p,1);
- return;
+ send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ myname,group,0,0,bcast_ip,myip);
}
-/****************************************************************************
-reply to a name status query
-****************************************************************************/
-static void reply_name_status(char *inbuf)
-{
- pstring outbuf;
- fstring qname;
- int rec_name_trn_id = RSVAL(inbuf,0);
- char *p = inbuf;
- struct in_addr tmpip;
- int i;
- int count=0;
- int name_type;
- BOOL wildcard = False;
-
- bzero(outbuf,sizeof(outbuf));
-
- name_type = name_extract(inbuf,12,qname);
- wildcard = (qname[0]=='*');
+/*******************************************************************
+ am I listening on a name. Should check name_type as well
- DEBUG(2,("(%s) status query on name (%s)\n",inet_ntoa(lastip), qname));
+ This is primarily used to prevent us gathering server lists from
+ other workgroups we aren't a part of
+ ******************************************************************/
+static BOOL listening(struct nmb_name *n)
+{
+ if (!strequal(n->scope,scope)) return(False);
+
+ if (strequal(n->name,myname) ||
+ strequal(n->name,PrimaryGroup) ||
+ strequal(n->name,MSBROWSE))
+ return(True);
- if (!wildcard) {
- i = find_name(qname,name_type,False);
+ return(False);
+}
- if (i < 0)
- return;
- if (names[i].source != SELF && names[i].source != LMHOSTS)
- return;
- }
- /* Send a POSITIVE NAME STATUS RESPONSE */
- RSSVAL(outbuf,0,rec_name_trn_id);
- CVAL(outbuf,2) = (1<<7) | (1<<2);
- CVAL(outbuf,3) = 0;
- RSSVAL(outbuf,4,0);
- RSSVAL(outbuf,6,1);
- RSSVAL(outbuf,8,0);
- RSSVAL(outbuf,10,0);
- p = outbuf+12;
- strcpy(p,inbuf+12);
- p += name_len(p);
- RSSVAL(p,0,0x21);
- RSSVAL(p,2,0x1);
- RSIVAL(p,4,0);
- RSSVAL(p,8,6);
- p += 10;
-
- for (i=0;i<num_names;i++)
- if (names[i].valid) count++;
- count = MIN(count,(512 - (46 + 1 + PTR_DIFF(p,outbuf)))/18);
+/*******************************************************************
+ process a domain announcement frame
- SCVAL(p,0,count);
- p++;
+ Announce frames come in 3 types. Servers send host announcements
+ (command=1) to let the master browswer know they are
+ available. Master browsers send local master announcements
+ (command=15) to let other masters and backups that they are the
+ master. They also send domain announcements (command=12) to register
+ the domain
+
+ The comment field of domain announcements contains the master
+ browser name. The servertype is used by NetServerEnum to select
+ resources. We just have to pass it to smbd (via browser.dat) and let
+ the client choose using bit masks.
+ ******************************************************************/
+static void process_announce(struct packet_struct *p,int command,char *buf)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ int update_count = CVAL(buf,0);
+ int ttl = IVAL(buf,1)/1000;
+ char *name = buf+5;
+ int major=CVAL(buf,21);
+ int minor=CVAL(buf,22);
+ uint32 servertype = IVAL(buf,23);
+ char *comment = buf+31;
+
+ name[15] = 0;
+ comment[43] = 0;
+
+ DEBUG(3,("Announce(%d) %s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n",
+ command,name,update_count,ttl,major,minor,
+ servertype,comment));
- for (i=0;i<num_names && count>0;i++)
- if (names[i].valid)
- {
- bzero(p,18);
- strcpy(p,names[i].name);
- strupper(p);
- p[15] = names[i].type;
- p += 16;
- p[0] = 0x4; /* active */
- if (strequal(names[i].name,myname)) p[0] |= 0x2; /* permanent */
- if (ISGROUP(i)) p[0] |= 0x80; /* group */
- p += 2;
- count--;
- }
+ if (strequal(dgram->source_name.name,myname)) return;
- bzero(p,46);
- putip(p,(char *)&myip);
- SIVAL(p,20,num_good_sends);
- SIVAL(p,24,num_good_receives);
-
- p += 46;
-
- tmpip = lastip;
- num_good_sends++;
- send_nmb(outbuf,PTR_DIFF(p,outbuf),&tmpip,lastport>0?lastport:137);
+ if (!listening(&dgram->dest_name)) return;
- return;
+ /* add them to our browse list */
+ add_server_entry(name,servertype,ttl,comment);
}
-/****************************************************************************
-reply to a name query
-****************************************************************************/
-static void reply_name_query(char *inbuf)
-{
- pstring outbuf;
- int rec_name_trn_id = RSVAL(inbuf,0);
- char qname[100]="";
- char *p = inbuf;
- unsigned char nb_flags = 0;
- int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
- struct in_addr tmpip;
- struct in_addr retip;
- int i=-1;
- BOOL broadcast = ((nm_flags&1) != 0);
- int name_type;
- int qtype;
- BOOL wildcard=False;
+/*******************************************************************
+ process a backup list request
- bzero(outbuf,sizeof(outbuf));
+ A client send a backup list request to ask for a list of servers on
+ the net that maintain server lists for a domain. A server is then
+ chosen from this list to send NetServerEnum commands to to list
+ available servers.
- name_type = name_extract(inbuf,12,qname);
+ Currently samba only sends back one name in the backup list, its
+ wn. For larger nets we'll have to add backups and send "become
+ backup" requests occasionally.
+ ******************************************************************/
+static void process_backup_list(struct packet_struct *p,char *buf)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ int count = CVAL(buf,0);
+ int token = IVAL(buf,1);
+
+ DEBUG(3,("Backup request to %s token=%d\n",
+ namestr(&dgram->dest_name),
+ token));
- wildcard = (qname[0] == '*');
+ if (strequal(dgram->source_name.name,myname)) return;
- qtype = RSVAL(inbuf+12+name_len(inbuf+12),0);
+ if (count <= 0) return;
- if (qtype == 0x21) {
- reply_name_status(inbuf);
+ if (!AM_MASTER ||
+ !strequal(PrimaryGroup,dgram->dest_name.name))
return;
- }
- if (qtype != 0x20)
- return;
+ if (!listening(&dgram->dest_name)) return;
- DEBUG(2,("(%s) querying name (%s)(%d) (%s)",
- inet_ntoa(lastip), qname, name_type,
- broadcast?"BROADCAST":"UNICAST"));
+ send_backup_list(myname,token,
+ &dgram->source_name,
+ p->ip);
+}
- if (!wildcard) {
- i = find_name(qname,name_type,False);
- if (i < 0)
- i = find_name(qname,name_type,True);
-
- if (i >= 0)
- {
- if (broadcast && (names[i].unicast || names[i].source == REGISTER)) {
- DEBUG(2,(" - broadcast. No reply\n"));
- return;
- }
+/*******************************************************************
+ work out if I win an election
+ ******************************************************************/
+static BOOL win_election(int version,uint32 criterion,int timeup,char *name)
+{
+ time_t t = time(NULL);
+ uint32 mycriterion;
+ if (version > ELECTION_VERSION) return(False);
+ if (version < ELECTION_VERSION) return(True);
- if (ISGROUP(i)) {
- DEBUG(2,(" - group name. No reply\n"));
- return;
- }
+ mycriterion = ElectionCriterion;
- retip = names[i].ip;
- DEBUG(2,(" sending positive reply\n"));
- }
- else
- {
- if ((name_type!=0 && name_type!=0x3 && name_type!=0x20) ||
- (broadcast && !dns_serve))
- {
- DEBUG(2,("\n"));
- return;
- }
- else
- /* try a DNS query to get the IP */
- {
- struct hostent *hp;
- pstring hname;
-
- StrnCpy(hname,qname,15);
- trim_string(hname," "," ");
- trim_string(hname,".",".");
- p = strchr(hname,' ');
- if (p) *p = 0;
-
- if ((hp = Get_Hostbyname(hname)) == 0)
- {
- DEBUG(2,(": unknown name sending no reply\n"));
- return;
- }
-
- putip((char *)&retip,(char *)hp->h_addr);
-
- if (broadcast && is_mynet(retip)) {
- DEBUG(2,(" on same subnet (%s), no reply\n",inet_ntoa(retip)));
- return;
- }
- i = find_name(qname,name_type,True);
- if (i < 0) {
- if ((i=add_name())>=0) {
- StrnCpy(names[i].name,qname,15);
- names[i].type = name_type;
- names[i].unicast = is_mynet(retip);
- names[i].ip = retip;
- names[i].valid = True;
- names[i].ttl = 120; /* give it two minutes */
- names[i].start_time = time(NULL);
- names[i].source = DNS;
- }
- }
- }
- DEBUG(2,(" sending positive reply (%s)\n",inet_ntoa(retip)));
- }
- } else {
- retip = myip;
- }
-
- /* Send a POSITIVE NAME QUERY RESPONSE */
- RSSVAL(outbuf,0,rec_name_trn_id);
- CVAL(outbuf,2) = (1<<7) | 0x5;
- CVAL(outbuf,3) = 0;
- RSSVAL(outbuf,4,0);
- RSSVAL(outbuf,6,1);
- RSSVAL(outbuf,8,0);
- RSSVAL(outbuf,10,0);
- p = outbuf+12;
- strcpy(p,inbuf+12);
- p += name_len(p);
- RSSVAL(p,0,0x20);
- RSSVAL(p,2,0x1);
- RSIVAL(p,4,0); /* my ttl ? */
- RSSVAL(p,8,6);
- CVAL(p,10) = nb_flags;
- CVAL(p,11) = 0;
- p += 12;
- putip(p,(char *)&retip);
- p += 4;
-
- show_nmb(outbuf);
-
- tmpip = lastip;
- num_good_sends++;
- send_nmb(outbuf,nmb_len(outbuf),&tmpip,lastport>0?lastport:137);
+ if (criterion > mycriterion) return(False);
+ if (criterion < mycriterion) return(True);
- return;
+ if (timeup > (t - StartupTime)) return(False);
+ if (timeup < (t - StartupTime)) return(True);
+
+ if (strcasecmp(myname,name) > 0) return(False);
+
+ return(True);
}
+/*******************************************************************
+ process a election packet
-/****************************************************************************
- construct a reply to the incoming packet
-****************************************************************************/
-void construct_reply(char *inbuf)
+ An election dynamically decides who will be the master.
+ ******************************************************************/
+static void process_election(struct packet_struct *p,char *buf)
{
- int opcode = CVAL(inbuf,2) >> 3;
- int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
- int rcode = CVAL(inbuf,3) & 0xF;
- int bcast = (nm_flags&1);
- int response = (CVAL(inbuf,2)>>7);
- int qdcount = RSVAL(inbuf,4);
- int arcount = RSVAL(inbuf,10);
+ struct dgram_packet *dgram = &p->packet.dgram;
+ int version = CVAL(buf,0);
+ uint32 criterion = IVAL(buf,1);
+ int timeup = IVAL(buf,5)/1000;
+ char *name = buf+13;
- /* if this is a response then ignore it */
- if (response || rcode) return;
+ name[15] = 0;
- if (!bcast && opcode == 0x5 && qdcount==1 && arcount==1)
- {
- reply_name_reg(inbuf);
- return;
- }
+ DEBUG(3,("Election request from %s vers=%d criterion=%08x timeup=%d\n",
+ name,version,criterion,timeup));
- if (opcode == 0 && qdcount==1)
- {
- reply_name_query(inbuf);
- return;
- }
+ if (strequal(dgram->source_name.name,myname)) return;
- if (!bcast && opcode == 6 && qdcount==1 && arcount==1)
- {
- reply_name_release(inbuf);
- return;
- }
+ if (!listening(&dgram->dest_name)) return;
- if (!bcast && ((opcode == 8) || (opcode == 9)) && qdcount==1 && arcount==1)
- {
- reply_name_reg(inbuf);
- return;
+ if (win_election(version,criterion,timeup,name)) {
+ if (!RunningElection) {
+ needelection = True;
+ ElectionCount=0;
+ }
+ } else {
+ needelection = False;
+ if (RunningElection) {
+ RunningElection = False;
+ DEBUG(3,(">>> Lost election on %s <<<\n",PrimaryGroup));
+
+ /* if we are the master then remove our masterly names */
+ if (AM_MASTER)
+ become_nonmaster();
}
+ }
}
-/****************************************************************************
-construct a host announcement unicast
-****************************************************************************/
-static BOOL send_udp_138(char *buf,int len,
- char *srcname,char *dstname,
- int src_type,int dest_type,
- struct in_addr dest_ip)
+/*******************************************************************
+ process a announcement request
+
+ clients send these when they want everyone to send an announcement
+ immediately. This can cause quite a storm of packets!
+ ******************************************************************/
+static void process_announce_request(struct packet_struct *p,char *buf)
{
- pstring outbuf;
- char *p,*p2;
- static int id=0;
- char tmp[4];
- struct sockaddr_in sock_out;
+ struct dgram_packet *dgram = &p->packet.dgram;
+ int flags = CVAL(buf,0);
+ char *name = buf+1;
- bzero(outbuf,sizeof(outbuf));
- RSSVAL(outbuf,0,0x1102); /* what is this? */
- RSSVAL(outbuf,2,++id);
- putip(outbuf+4,(void *)&myip);
- RSSVAL(outbuf,8,138);
- RSSVAL(outbuf,12,0);
- p = outbuf + 14;
- p += name_mangle(srcname,p,src_type);
- p += name_mangle(dstname,p,dest_type);
-
- /* now setup the smb part */
- p -= 4;
- memcpy(tmp,p,4);
- set_message(p,17,17 + len,True);
- memcpy(p,tmp,4);
-
- CVAL(p,smb_com) = SMBtrans;
- SSVAL(p,smb_vwv1,len);
- SSVAL(p,smb_vwv11,len);
- SSVAL(p,smb_vwv12,86);
- SSVAL(p,smb_vwv13,3);
- SSVAL(p,smb_vwv14,1);
- SSVAL(p,smb_vwv15,1);
- SSVAL(p,smb_vwv16,2);
- p2 = smb_buf(p);
- strcpy(p2,"\\MAILSLOT\\BROWSE");
- p2 = skip_string(p2,1);
-
- memcpy(p2,buf,len);
- p2 += len;
-
- len = PTR_DIFF(p2,outbuf);
- RSSVAL(outbuf,10,len);
-
-
- /* set the address and port */
- bzero((char *)&sock_out,sizeof(sock_out));
- putip((char *)&sock_out.sin_addr,(char *)&dest_ip);
- sock_out.sin_port = htons(138);
- sock_out.sin_family = AF_INET;
-
- /* log the packet */
- log_out(outbuf,len);
-
- /* send it */
- if (sendto(Client138,outbuf,len,0,
- (struct sockaddr *)&sock_out,sizeof(sock_out)) < 0) {
- DEBUG(3,("Sendto failed errno=%d (%s)\n",errno,strerror(errno)));
- return(False);
- } else {
- num_good_sends++;
- }
- return(True);
+ name[15] = 0;
+
+ DEBUG(3,("Announce request from %s flags=0x%X\n",name,flags));
+
+ if (strequal(dgram->source_name.name,myname)) return;
+
+ needannounce = True;
}
+
/****************************************************************************
-construct a host announcement unicast
+process a browse frame
****************************************************************************/
-static void announce_host(int i,char *my_name,char *Comment)
+static void process_browse_packet(struct packet_struct *p,char *buf,int len)
{
- static int announce_interval = 1;
- char *group = names[i].name;
- struct in_addr dest_ip = names[i].ip;
- pstring outbuf;
- char *p;
+ int command = CVAL(buf,0);
+ switch (command)
+ {
+ case 1: /* host announce */
+ case 12: /* domain announce */
+ case 15: /* local master announce */
+ process_announce(p,command,buf+1);
+ break;
- names[i].count++;
+ case 2: /* announce request */
+ process_announce_request(p,buf+1);
+ break;
- if ((names[i].count % announce_interval) != 0) return;
+ case 8: /* election */
+ process_election(p,buf+1);
+ break;
- if (announce_interval < 2) announce_interval++;
+ case 9: /* get backup list */
+ process_backup_list(p,buf+1);
+ break;
+ }
+}
- DEBUG(2,("Sending host announcement to %s for group %s\n",
- inet_ntoa(dest_ip),group));
- if (!*Comment) Comment = "NoComment";
- if (!*my_name) my_name = "NoName";
- if (!*group) group = "NoGroup";
+/****************************************************************************
+process udp 138 datagrams
+****************************************************************************/
+static void process_dgram(struct packet_struct *p)
+{
+ char *buf;
+ char *buf2;
+ int len;
+ struct dgram_packet *dgram = &p->packet.dgram;
- if (strlen(Comment) > 47) Comment[47] = 0;
+ if (dgram->header.msg_type != 0x10 &&
+ dgram->header.msg_type != 0x11 &&
+ dgram->header.msg_type != 0x12) {
+ /* don't process error packets etc yet */
+ return;
+ }
- bzero(outbuf,sizeof(outbuf));
- p = outbuf;
- CVAL(p,0) = 1; /* host announce */
- SSVAL(p,1,0x6006); /* update count?? */
- CVAL(p,3) = 0xEA; /* res1 */
- SSVAL(p,4,announce_interval);
- p += 6;
- StrnCpy(p,my_name,16);
- strupper(p);
- p += 16;
- CVAL(p,0) = 1; /* major version (was 1) */
- CVAL(p,1) = 0x33; /* minor version (was 51) */
- SIVAL(p,2,0xB03); /* server and w'station + unix + printq + domain member*/
- SSVAL(p,6,0x30B); /* election version */
- SSVAL(p,8,0xAA55); /* browse constant */
- p += 10;
- strcpy(p,Comment);
- p += strlen(p)+1;
+ buf = &dgram->data[0];
+ buf -= 4; /* XXXX for the pseudo tcp length -
+ someday I need to get rid of this */
- send_udp_138(outbuf,PTR_DIFF(p,outbuf),my_name,group,0,0x1d,dest_ip);
-}
+ if (CVAL(buf,smb_com) != SMBtrans) return;
+ len = SVAL(buf,smb_vwv11);
+ buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
+ DEBUG(3,("datagram from %s to %s for %s of type %d len=%d\n",
+ namestr(&dgram->source_name),namestr(&dgram->dest_name),
+ smb_buf(buf),CVAL(buf2,0),len));
-/****************************************************************************
-send a name registration packet
-****************************************************************************/
-static void send_registration(char *name,int name_type,struct in_addr dest_ip,struct in_addr ip,BOOL refresh,int ttl)
-{
- char *p;
- static int t = 0x176;
- pstring outbuf;
- bzero(outbuf,sizeof(outbuf));
- /* send a registration request */
- RSSVAL(outbuf,0,t++);
- if (refresh)
- CVAL(outbuf,2) = (0<<7) | (9<<3) | 0;
- else
- CVAL(outbuf,2) = (0<<7) | (5<<3) | 1;
-
- CVAL(outbuf,3) = (1<<4);
- RSSVAL(outbuf,4,1);
- RSSVAL(outbuf,6,0);
- RSSVAL(outbuf,8,0);
- RSSVAL(outbuf,10,1);
- p = outbuf+12;
- name_mangle(name,p,name_type);
- p += name_len(p);
- RSSVAL(p,0,0x20);
- RSSVAL(p,2,0x1);
- p += 4;
- RSSVAL(p,0,12);
- CVAL(p,0) = CVAL(p,0) | 0xC0;
- p += 2;
- RSSVAL(p,0,0x20);
- RSSVAL(p,2,0x1);
- p += 4;
- RSIVAL(p,0,ttl);
-
- RSSVAL(p,4,6);
- RSSVAL(p,6,0);
- p += 8;
- putip(p,&ip);
- p += 4;
-
- DEBUG(2,("Sending a name registration request\n"));
- if (DEBUGLEVEL > 2)
- show_nmb(outbuf);
+ /* only understand browse datagrams */
+ if (!strequal(smb_buf(buf),"\\MAILSLOT\\BROWSE"))
+ return;
- num_good_sends++;
- send_nmb(outbuf,PTR_DIFF(p,outbuf),&dest_ip,137);
+ if (len <= 0) return;
+ process_browse_packet(p,buf2,len);
}
/*******************************************************************
-find a master browser
-********************************************************************/
-BOOL find_master(char *name1,struct in_addr ip,struct in_addr *ipout,
- void (*fn)())
+ find a workgroup using the specified broadcast
+ ******************************************************************/
+static BOOL find_workgroup(char *name,struct in_addr ip)
{
- int type = 0x1d;
- fstring name;
+ fstring name1;
BOOL ret;
- strcpy(name,name1);
- if (strequal(name,"*")) {
- strcpy(name,"\001\002__MSBROWSE__\002");
- type = 1;
- }
- ret = name_query(name,type,True,ip,ipout,fn);
+ struct in_addr ipout;
+
+ strcpy(name1,MSBROWSE);
+
+ ret = name_query(ClientNMB,name1,0x1,True,False,ip,&ipout,queue_packet);
if (!ret) return(False);
- if (type != 1) return(True);
- name_status(name,type,*ipout,fn,name1);
- return(name1[0] != '*');
+ name_status(ClientNMB,name1,0x1,False,ipout,name,queue_packet);
+
+ if (name[0] != '*') {
+ DEBUG(2,("Found workgroup %s on broadcast %s\n",name,inet_ntoa(ip)));
+ } else {
+ DEBUG(3,("Failed to find workgroup %s on broadcast %s\n",name,inet_ntoa(ip)));
+ }
+ return(name[0] != '*');
}
+
/****************************************************************************
-process a workgroup announce frame
-****************************************************************************/
-static void process_workgroup_announce(char *group,struct in_addr ip)
+ a hook for announce handling - called every minute
+ **************************************************************************/
+static void do_announcements(void)
{
- int i;
- for (i=0;i<num_names;i++)
- if (names[i].valid) {
- if (names[i].name[0] == '*') {
- StrnCpy(names[i].name,group,15);
- names[i].master_ip = ip;
- names[i].found_master = True;
- names[i].count=0;
- announce_host(i,myname,comment);
- return;
- }
- if (names[i].isgroup && name_equal(names[i].name,group,0,0)) {
- int j;
- for (j=i;j<num_names;j++)
- if (names[j].valid && names[j].isgroup && names[i].found_master &&
- name_equal(names[i].name,group,0,0)) return;
- names[i].master_ip = ip;
- names[i].found_master = True;
- names[i].count=0;
- announce_host(i,myname,comment);
- return;
+ struct domain_record *d;
+
+ for (d = domainlist; d; d = d->next) {
+ /* if the ip address is 0 then set to the broadcast */
+ if (zero_ip(d->bcast_ip)) d->bcast_ip = bcast_ip;
+
+ /* if the workgroup is '*' then find a workgroup to be part of */
+ if (d->name[0] == '*') {
+ if (!find_workgroup(d->name,d->bcast_ip)) continue;
+ add_host_entry(d->name,0x1e,False,0,SELF,
+ *interpret_addr2("255.255.255.255"));
+ if (!*PrimaryGroup && ip_equal(bcast_ip,d->bcast_ip)) {
+ strcpy(PrimaryGroup,d->name);
+ strupper(PrimaryGroup);
}
}
+
+ announce_host(d,myname,ServerComment);
+ }
+
+ needannounce=False;
}
+/*******************************************************************
+ check if someone still owns a name
+ ******************************************************************/
+static BOOL confirm_name(struct name_record *n)
+{
+ struct in_addr ipout;
+ BOOL ret = name_query(ClientNMB,n->name.name,
+ n->name.name_type,False,
+ False,n->ip,&ipout,queue_packet);
+ return(ret && ip_equal(ipout,n->ip));
+}
/****************************************************************************
-process a browse frame
+reply to a name release
****************************************************************************/
-static void process_browse_packet(char *buf,int len)
+static void reply_name_release(struct packet_struct *p)
{
- char *p;
- int command = CVAL(buf,0);
- switch (command) {
- case 0xc: /* workgroup announcement */
- {
- fstring group;
- p = buf + 6;
- StrnCpy(group,p,15);
- DEBUG(2,("Got workgroup announce for %s (%s)\n",
- group,inet_ntoa(lastip)));
- process_workgroup_announce(group,lastip);
- break;
+ struct nmb_packet *nmb = &p->packet.nmb;
+ struct packet_struct p2;
+ struct nmb_packet *nmb2;
+ struct res_rec answer_rec;
+ struct in_addr ip;
+ int rcode=0;
+ int nb_flags = nmb->additional->rdata[0];
+ BOOL bcast = nmb->header.nm_flags.bcast;
+
+
+ putip((char *)&ip,&nmb->additional->rdata[2]);
+
+ {
+ struct name_record *n = find_name(&nmb->question.question_name);
+ if (n && n->unique && n->source == REGISTER &&
+ ip_equal(ip,n->ip)) {
+ remove_name(n); n = NULL;
}
+
+ /* XXXX under what conditions should we reject the removal?? */
}
+ DEBUG(3,("Name release on name %s rcode=%d\n",
+ namestr(&nmb->question.question_name),rcode));
+
+ if (bcast) return;
+
+ /* Send a NAME RELEASE RESPONSE */
+ p2 = *p;
+ nmb2 = &p2.packet.nmb;
+
+ nmb2->header.response = True;
+ nmb2->header.nm_flags.bcast = False;
+ nmb2->header.nm_flags.recursion_available = CanRecurse;
+ nmb2->header.nm_flags.trunc = False;
+ nmb2->header.nm_flags.authoritative = True;
+ nmb2->header.qdcount = 0;
+ nmb2->header.ancount = 1;
+ nmb2->header.nscount = 0;
+ nmb2->header.arcount = 0;
+ nmb2->header.rcode = rcode;
+
+ nmb2->answers = &answer_rec;
+ bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
+
+ nmb2->answers->rr_name = nmb->question.question_name;
+ nmb2->answers->rr_type = nmb->question.question_type;
+ nmb2->answers->rr_class = nmb->question.question_class;
+ nmb2->answers->ttl = 0;
+ nmb2->answers->rdlength = 6;
+ nmb2->answers->rdata[0] = nb_flags;
+ putip(&nmb2->answers->rdata[2],(char *)&ip);
+
+ send_packet(&p2);
}
/****************************************************************************
-process udp 138 datagrams
-****************************************************************************/
-static void process_138(void)
-{
- pstring inbuf;
- int len;
- while (read_max_udp(Client138,inbuf,sizeof(inbuf),1) > 4) {
- char *p = inbuf;
- len = RSVAL(inbuf,10);
- p += 14;
- p += name_len(p);
- p += name_len(p);
- p -= 4;
- if (CVAL(p,smb_com) != SMBtrans) continue;
- if (!strequal(smb_buf(p),"\\MAILSLOT\\BROWSE")) continue;
- len = SVAL(p,smb_vwv11);
- p = smb_base(p) + SVAL(p,smb_vwv12);
- if (len <= 0) continue;
- process_browse_packet(p,len);
+ reply to a reg request
+ **************************************************************************/
+static void reply_name_reg(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ char *qname = nmb->question.question_name.name;
+ BOOL wildcard = (qname[0] == '*');
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ int ttl = nmb->additional->ttl;
+ int name_type = nmb->question.question_name.name_type;
+ int nb_flags = nmb->additional->rdata[0];
+ struct packet_struct p2;
+ struct nmb_packet *nmb2;
+ struct res_rec answer_rec;
+ struct in_addr ip;
+ BOOL group = (nb_flags&0x80)?True:False;
+ int rcode = 0;
+
+ if (wildcard) return;
+
+ putip((char *)&ip,&nmb->additional->rdata[2]);
+
+ if (group) {
+ /* apparently we should return 255.255.255.255 for group queries (email from MS) */
+ ip = *interpret_addr2("255.255.255.255");
+ }
+
+ {
+ struct name_record *n = find_name(&nmb->question.question_name);
+
+ if (n) {
+ if (!group && !ip_equal(ip,n->ip)) {
+ /* check if the previous owner still wants it,
+ if so reject the registration, otherwise change the owner
+ and refresh */
+ if (n->source != REGISTER || confirm_name(n)) {
+ rcode = 6;
+ } else {
+ n->ip = ip;
+ n->death_time = ttl?p->timestamp+ttl*3:0;
+ DEBUG(3,("%s changed owner to %s\n",
+ namestr(&n->name),inet_ntoa(n->ip)));
+ }
+ } else {
+ /* refresh the name */
+ if (n->source != SELF)
+ n->death_time = ttl?p->timestamp + ttl*3:0;
+ }
+ } else {
+ /* add the name to our database */
+ n = add_host_entry(qname,name_type,!group,ttl,REGISTER,ip);
+ }
}
+
+ if (bcast) return;
+
+ DEBUG(3,("Name registration for name %s at %s rcode=%d\n",
+ namestr(&nmb->question.question_name),
+ inet_ntoa(ip),rcode));
+
+ /* Send a NAME REGISTRATION RESPONSE */
+ /* a lot of fields get copied from the query. This gives us the IP
+ and port the reply will be sent to etc */
+ p2 = *p;
+ nmb2 = &p2.packet.nmb;
+
+ nmb2->header.opcode = 5;
+ nmb2->header.response = True;
+ nmb2->header.nm_flags.bcast = False;
+ nmb2->header.nm_flags.recursion_available = CanRecurse;
+ nmb2->header.nm_flags.trunc = False;
+ nmb2->header.nm_flags.authoritative = True;
+ nmb2->header.qdcount = 0;
+ nmb2->header.ancount = 1;
+ nmb2->header.nscount = 0;
+ nmb2->header.arcount = 0;
+ nmb2->header.rcode = rcode;
+
+ nmb2->answers = &answer_rec;
+ bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
+
+ nmb2->answers->rr_name = nmb->question.question_name;
+ nmb2->answers->rr_type = nmb->question.question_type;
+ nmb2->answers->rr_class = nmb->question.question_class;
+
+ nmb2->answers->ttl = ttl;
+ nmb2->answers->rdlength = 6;
+ nmb2->answers->rdata[0] = nb_flags;
+ putip(&nmb2->answers->rdata[2],(char *)&ip);
+
+ send_packet(&p2);
}
+
/****************************************************************************
-a hook for registration of my own names
+reply to a name status query
****************************************************************************/
-static void do_registration_hook(void)
+static void reply_name_status(struct packet_struct *p)
{
- static int count = 0;
- static time_t last_t=0;
- time_t t = time(NULL);
-
- if (last_t && (t-last_t)<REGISTRATION_INTERVAL) return;
- last_t = t;
+ struct nmb_packet *nmb = &p->packet.nmb;
+ char *qname = nmb->question.question_name.name;
+ BOOL wildcard = (qname[0] == '*');
+ struct packet_struct p2;
+ struct nmb_packet *nmb2;
+ struct res_rec answer_rec;
+ char *buf;
+ int count;
+ int rcode = 0;
+ struct name_record *n = find_name(&nmb->question.question_name);
+
+ DEBUG(3,("Name status for name %s\n",
+ namestr(&nmb->question.question_name)));
+
+ if (!wildcard && (!n || n->source != SELF))
+ return;
+
+ /* Send a POSITIVE NAME STATUS RESPONSE */
+ /* a lot of fields get copied from the query. This gives us the IP
+ and port the reply will be sent to etc */
+ p2 = *p;
+ nmb2 = &p2.packet.nmb;
+
+ nmb2->header.response = True;
+ nmb2->header.nm_flags.bcast = False;
+ nmb2->header.nm_flags.recursion_available = CanRecurse;
+ nmb2->header.nm_flags.trunc = False;
+ nmb2->header.nm_flags.authoritative = True; /* WfWg ignores
+ non-authoritative answers */
+ nmb2->header.qdcount = 0;
+ nmb2->header.ancount = 1;
+ nmb2->header.nscount = 0;
+ nmb2->header.arcount = 0;
+ nmb2->header.rcode = rcode;
+
+ nmb2->answers = &answer_rec;
+ bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
+
+
+ nmb2->answers->rr_name = nmb->question.question_name;
+ nmb2->answers->rr_type = nmb->question.question_type;
+ nmb2->answers->rr_class = nmb->question.question_class;
+ nmb2->answers->ttl = 0;
+
+ for (count=0, n = namelist ; n; n = n->next) {
+ if (n->source != SELF) continue;
+ count++;
+ }
+
+ count = MIN(count,400/18); /* XXXX hack, we should calculate exactly
+ how many will fit */
+
- send_registration(myname,0x20,bcast_ip,myip,count>0,300000);
- count++;
+ buf = &nmb2->answers->rdata[0];
+ SCVAL(buf,0,count);
+ buf += 1;
+
+ for (n = namelist ; n; n = n->next)
+ {
+ if (n->source != SELF) continue;
+
+ bzero(buf,18);
+ strcpy(buf,n->name.name);
+ strupper(buf);
+ buf[15] = n->name.name_type;
+ buf += 16;
+ buf[0] = 0x4; /* active */
+ if (!n->unique) buf[0] |= 0x80; /* group */
+ buf += 2;
+ count--;
+ }
+
+ /* XXXXXXX we should fill in more fields of the statistics structure */
+ bzero(buf,46);
+ putip(buf,(char *)&myip);
+ {
+ extern int num_good_sends,num_good_receives;
+ SIVAL(buf,20,num_good_sends);
+ SIVAL(buf,24,num_good_receives);
+ }
+
+ buf += 46;
+
+ nmb2->answers->rdlength = PTR_DIFF(buf,&nmb2->answers->rdata[0]);
+
+ send_packet(&p2);
}
+
+
/****************************************************************************
-a hook for browsing handling - called every BROWSE_INTERVAL secs
+reply to a name query
****************************************************************************/
-static void do_browse_hook(void)
+static void reply_name_query(struct packet_struct *p)
{
- static BOOL first = True;
- int i;
- static time_t last_t=0;
- time_t t = time(NULL);
-
- if (last_t && (t-last_t)<browse_interval) return;
- last_t = t;
+ struct nmb_packet *nmb = &p->packet.nmb;
+ char *qname = nmb->question.question_name.name;
+ BOOL wildcard = (qname[0] == '*');
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ struct in_addr retip;
+ int name_type = nmb->question.question_name.name_type;
+ struct packet_struct p2;
+ struct nmb_packet *nmb2;
+ struct res_rec answer_rec;
+ int ttl=0;
+ int rcode=0;
+ BOOL unique = True;
+
+ DEBUG(3,("Name query for %s from %s (bcast=%s) - ",
+ namestr(&nmb->question.question_name),
+ inet_ntoa(p->ip),
+ BOOLSTR(bcast)));
- for (i=0;i<num_names;i++)
- {
- BOOL old_found_master = names[i].found_master;
+ if (wildcard)
+ retip = myip;
- if (!NAMEVALID(i) || !ISGROUP(i)) continue;
+ if (!wildcard) {
+ struct name_record *n = find_name(&nmb->question.question_name);
- if (names[i].found_master) {
- struct in_addr ip2;
- announce_host(i,myname,comment);
-
- if (!name_query(names[i].name,0x1d,True,
- names[i].master_ip,
- &ip2,construct_reply)) {
- DEBUG(2,("%s Master browser at %s failed to respond\n",
- timestring(),
- inet_ntoa(names[i].master_ip)));
- names[i].found_master = False;
- } else {
- names[i].master_ip = ip2;
- }
- }
+ if (!n) {
+ struct in_addr ip;
+ unsigned long a;
- if (!names[i].found_master) {
- struct in_addr ip2;
- names[i].found_master = find_master(names[i].name,names[i].ip,&ip2,
- construct_reply);
-
- if (names[i].found_master) {
- names[i].master_ip = ip2;
- DEBUG(1,("%s New master browser for %s at %s\n",
- timestring(),
- names[i].name,inet_ntoa(names[i].master_ip)));
- names[i].count = 0;
- announce_host(i,myname,comment);
- }
+ /* only do DNS lookups if the query is for type 0x20 or type 0x0 */
+ if (name_type != 0x20 && name_type != 0) {
+ DEBUG(3,("not found\n"));
+ return;
}
- if (!names[i].found_master) {
- int level = (old_found_master||first)?1:2;
- DEBUG(level,("%s Failed to find a master browser for %s using %s\n",
- timestring(),
- names[i].name,inet_ntoa(names[i].ip)));
+ /* look it up with DNS */
+ a = interpret_addr(qname);
+
+ if (!a) {
+ /* no luck with DNS. We could possibly recurse here XXXX */
+ /* if this isn't a bcast then we should send a negative reply XXXX */
+ DEBUG(3,("no recursion\n"));
+ return;
}
+
+ /* add it to our cache of names. give it 2 hours in the cache */
+ putip((char *)&ip,(char *)&a);
+ n = add_host_entry(qname,name_type,True,2*60*60,DNS,ip);
+
+ /* failed to add it? yikes! */
+ if (!n) return;
+ }
+
+ /* don't respond to bcast queries for group names unless we own them */
+ if (bcast && !n->unique && !n->source == SELF) {
+ DEBUG(3,("no bcast replies\n"));
+ return;
+ }
+
+ /* don't respond to bcast queries for addresses on the same net as the
+ machine doing the querying unless its our IP */
+ if (bcast &&
+ n->source != SELF &&
+ same_net(n->ip,p->ip)) {
+ DEBUG(3,("same net\n"));
+ return;
}
- first = False;
+
+ /* is our entry already dead? */
+ if (n->death_time) {
+ if (n->death_time < p->timestamp) return;
+ ttl = n->death_time - p->timestamp;
+ }
+
+ retip = n->ip;
+ unique = n->unique;
+ }
+
+ /* if the IP is 0 then substitute my IP - we should see which one is on the
+ right interface for the caller to do this right XXX */
+ if (zero_ip(retip)) retip = myip;
+
+ DEBUG(3,("OK %s rcode=%d\n",inet_ntoa(retip),rcode));
+
+ /* a lot of fields get copied from the query. This gives us the IP
+ and port the reply will be sent to etc */
+ p2 = *p;
+ nmb2 = &p2.packet.nmb;
+
+ nmb2->header.response = True;
+ nmb2->header.nm_flags.bcast = False;
+ nmb2->header.nm_flags.recursion_available = CanRecurse;
+ nmb2->header.nm_flags.trunc = False;
+ nmb2->header.nm_flags.authoritative = True; /* WfWg ignores
+ non-authoritative answers */
+ nmb2->header.qdcount = 0;
+ nmb2->header.ancount = 1;
+ nmb2->header.nscount = 0;
+ nmb2->header.arcount = 0;
+ nmb2->header.rcode = rcode;
+
+ nmb2->answers = &answer_rec;
+ bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
+
+ nmb2->answers->rr_name = nmb->question.question_name;
+ nmb2->answers->rr_type = nmb->question.question_type;
+ nmb2->answers->rr_class = nmb->question.question_class;
+ nmb2->answers->ttl = ttl;
+ nmb2->answers->rdlength = 6;
+ nmb2->answers->rdata[0] = unique?0:0x80;
+ nmb2->answers->rdata[1] = 0;
+ putip(&nmb2->answers->rdata[2],(char *)&retip);
+
+ send_packet(&p2);
+}
+
+
+
+/* the global packet linked-list. incoming entries are added to the
+ end of this list. it is supposed to remain fairly short so we
+ won't bother with an end pointer. */
+static struct packet_struct *packet_queue = NULL;
+
+
+/*******************************************************************
+ queue a packet into the packet queue
+ ******************************************************************/
+static void queue_packet(struct packet_struct *packet)
+{
+ struct packet_struct *p;
+ if (!packet_queue) {
+ packet->prev = NULL;
+ packet->next = NULL;
+ packet_queue = packet;
+ return;
+ }
+
+ /* find the bottom */
+ for (p=packet_queue;p->next;p=p->next) ;
+
+ p->next = packet;
+ packet->next = NULL;
+ packet->prev = p;
}
/****************************************************************************
- process commands from the client
-****************************************************************************/
-void process(void)
+ process a nmb packet
+ ****************************************************************************/
+static void process_nmb(struct packet_struct *p)
{
- pstring inbuf;
- static int trans_num = 0;
- int nread;
+ struct nmb_packet *nmb = &p->packet.nmb;
- bzero(inbuf,sizeof(inbuf));
+ /* if this is a response then ignore it */
+ if (nmb->header.response) return;
- while (True)
+ switch (nmb->header.opcode)
{
- if (!browse)
+ case 5:
+ case 8:
+ case 9:
+ if (nmb->header.qdcount>0 &&
+ nmb->header.arcount>0) {
+ reply_name_reg(p);
+ return;
+ }
+ break;
+
+ case 0:
+ if (nmb->header.qdcount>0)
{
- if (!(nread = receive_nmb(inbuf,is_daemon?0:idle_timeout)))
+ switch (nmb->question.question_type)
{
- if (is_daemon) continue;
- return;
+ case 0x20:
+ reply_name_query(p);
+ break;
+
+ case 0x21:
+ reply_name_status(p);
+ break;
}
+ return;
}
- else
- {
- fd_set fds;
- int selrtn;
- struct timeval timeout;
+ break;
- do_registration_hook();
+ case 6:
+ if (nmb->header.qdcount>0 &&
+ nmb->header.arcount>0) {
+ reply_name_release(p);
+ return;
+ }
+ break;
+ }
- do_browse_hook();
+}
- process_138();
- FD_ZERO(&fds);
- FD_SET(Client,&fds);
- timeout.tv_sec = NMBD_SELECT_LOOP;
- timeout.tv_usec = 0;
+/*******************************************************************
+ run elements off the packet queue till its empty
+ ******************************************************************/
+static void run_packet_queue(void)
+{
+ struct packet_struct *p;
- selrtn = sys_select(&fds,&timeout);
+ while ((p=packet_queue)) {
+ switch (p->packet_type)
+ {
+ case NMB_PACKET:
+ process_nmb(p);
+ break;
- if (!FD_ISSET(Client,&fds))
- continue;
+ case DGRAM_PACKET:
+ process_dgram(p);
+ break;
+ }
- nread = read_udp_socket(Client, inbuf, sizeof(pstring));
- if (nread <= 0)
- continue;
- num_good_receives++;
- }
+ packet_queue = packet_queue->next;
+ if (packet_queue) packet_queue->prev = NULL;
+ free_packet(p);
+ }
+}
- if (nread < 4)
- continue;
- if (DEBUGLEVEL > 2)
- show_nmb(inbuf);
+/****************************************************************************
+ The main select loop, listen for packets and respond
+ ***************************************************************************/
+void process(void)
+{
+
+ while (True)
+ {
+ fd_set fds;
+ int selrtn;
+ struct timeval timeout;
+
+ if (needelection && *PrimaryGroup && !RunningElection) {
+ DEBUG(3,(">>> Starting election on %s <<<\n",PrimaryGroup));
+ ElectionCount = 0;
+ RunningElection = True;
+ needelection = False;
+ }
+
+ FD_ZERO(&fds);
+ FD_SET(ClientNMB,&fds);
+ FD_SET(ClientDGRAM,&fds);
+ /* during elections we need to send election packets at one
+ second intervals */
+ timeout.tv_sec = RunningElection?1:NMBD_SELECT_LOOP;
+ timeout.tv_usec = 0;
+
+ selrtn = sys_select(&fds,&timeout);
+
+ if (FD_ISSET(ClientNMB,&fds)) {
+ struct packet_struct *packet = read_packet(ClientNMB,NMB_PACKET);
+ if (packet) queue_packet(packet);
+ }
+
+ if (FD_ISSET(ClientDGRAM,&fds)) {
+ struct packet_struct *packet = read_packet(ClientDGRAM,DGRAM_PACKET);
+ if (packet) queue_packet(packet);
+ }
+
+ if (RunningElection)
+ run_election();
- DEBUG(2,("%s Transaction %d\n",timestring(),trans_num));
+ run_packet_queue();
- construct_reply(inbuf);
+ do_announcements();
- trans_num++;
+ housekeeping();
}
}
@@ -1688,27 +1784,59 @@
}
if (isdaemon)
- Client = open_socket_in(SOCK_DGRAM, port,*lookup?3:0);
+ ClientNMB = open_socket_in(SOCK_DGRAM, port,0);
else
- Client = 0;
+ ClientNMB = 0;
- Client138 = open_socket_in(SOCK_DGRAM,138,3);
+ ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3);
- if (Client == -1)
+ if (ClientNMB == -1)
return(False);
signal(SIGPIPE, SIGNAL_CAST sig_pipe);
- set_socket_options(Client,"SO_BROADCAST");
- set_socket_options(Client138,"SO_BROADCAST");
- set_socket_options(Client,user_socket_options);
-
+ set_socket_options(ClientNMB,"SO_BROADCAST");
+ set_socket_options(ClientDGRAM,"SO_BROADCAST");
DEBUG(3, ("Socket opened.\n"));
return True;
}
+/*******************************************************************
+ check that a IP, bcast and netmask and consistent. Must be a 1s
+ broadcast
+ ******************************************************************/
+static BOOL ip_consistent(struct in_addr ip,struct in_addr bcast,
+ struct in_addr nmask)
+{
+ unsigned long a_ip,a_bcast,a_nmask;
+
+ a_ip = ntohl(ip.s_addr);
+ a_bcast = ntohl(bcast.s_addr);
+ a_nmask = ntohl(nmask.s_addr);
+
+ /* check the netmask is sane */
+ if (((a_nmask>>24)&0xFF) != 0xFF) {
+ DEBUG(0,("Insane netmask %s\n",inet_ntoa(nmask)));
+ return(False);
+ }
+
+ /* check the IP and bcast are on the same net */
+ if ((a_ip&a_nmask) != (a_bcast&a_nmask)) {
+ DEBUG(0,("IP and broadcast are on different nets!\n"));
+ return(False);
+ }
+
+ /* check the IP and bcast are on the same net */
+ if ((a_bcast|a_nmask) != 0xFFFFFFFF) {
+ DEBUG(0,("Not a ones based broadcast %s\n",inet_ntoa(bcast)));
+ return(False);
+ }
+
+ return(True);
+}
+
/****************************************************************************
initialise connect, service and file structs
****************************************************************************/
@@ -1737,11 +1865,14 @@
Netmask = ip2;
}
- DEBUG(1,("Using IP %s ",inet_ntoa(myip))); /* core dump reported
- doing this. Why?? XXXXX */
+ DEBUG(1,("Using IP %s ",inet_ntoa(myip)));
DEBUG(1,("broadcast %s ",inet_ntoa(bcast_ip)));
DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));
+ if (!ip_consistent(myip,bcast_ip,Netmask)) {
+ DEBUG(0,("WARNING: The IP address, broadcast and Netmask are not consistent\n"));
+ DEBUG(0,("You are likely to experience problems with this setup!\n"));
+ }
}
if (! *myname) {
@@ -1751,9 +1882,12 @@
if (p) *p = 0;
}
- add_host_name(myname,0x20,&myip);
- add_host_name(myname,0x0,&myip);
- add_host_name(myname,0x3,&myip);
+ if (lp_preferred_master()) {
+ needelection = True;
+ ElectionCriterion |= (1<<3);
+ }
+
+ ElectionCriterion |= (lp_os_level() << 28);
return True;
}
@@ -1768,21 +1902,14 @@
printf("Usage: %s [-n name] [-B bcast address] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
printf("Version %s\n",VERSION);
printf("\t-D become a daemon\n");
- printf("\t-P passive only. don't respond\n");
- printf("\t-R only reply to queries, don't actively send claims\n");
printf("\t-p port listen on the specified port\n");
printf("\t-d debuglevel set the debuglevel\n");
printf("\t-l log basename. Basename for log/debug files\n");
printf("\t-n netbiosname. the netbios name to advertise for this host\n");
printf("\t-B broadcast address the address to use for broadcasts\n");
printf("\t-N netmask the netmask to use for subnet determination\n");
- printf("\t-L name lookup this netbios name then exit\n");
- printf("\t-S serve queries via DNS if not on the same subnet\n");
printf("\t-H hosts file load a netbios hosts file\n");
printf("\t-G group name add a group name to be part of\n");
- printf("\t-b toggles browsing support (defaults to on)\n");
- printf("\t-M group name searches for a master browser for the given group\n");
- printf("\t-T interval sets the browse announcement interval in seconds\n");
printf("\t-C comment sets the machine comment that appears in browse lists\n");
printf("\n");
}
@@ -1790,16 +1917,21 @@
/****************************************************************************
main program
-****************************************************************************/
+ **************************************************************************/
int main(int argc,char *argv[])
{
- int port = 137;
+ int port = NMB_PORT;
int opt;
- unsigned int lookup_type = 0;
extern FILE *dbf;
extern char *optarg;
- *lookup = *host_file = 0;
+ *host_file = 0;
+
+#if 0
+ sleep(10);
+#endif
+
+ StartupTime = time(NULL);
TimeInit();
@@ -1822,65 +1954,39 @@
signal(SIGHUP,SIGNAL_CAST sig_hup);
+ bcast_ip = *interpret_addr2("0.0.0.0");
+ myip = *interpret_addr2("0.0.0.0");
- while ((opt = getopt (argc, argv, "T:O:M:I:C:bAL:i:B:N:Rn:l:d:Dp:hPSH:G:")) != EOF)
+ while ((opt = getopt (argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:")) != EOF)
switch (opt)
{
- case 'T':
- browse_interval = atoi(optarg);
- browse_interval = MAX(browse_interval,10);
- break;
- case 'O':
- strcpy(user_socket_options,optarg);
+ case 's':
+ strcpy(servicesf,optarg);
break;
case 'C':
- strcpy(comment,optarg);
+ strcpy(ServerComment,optarg);
break;
case 'G':
- add_group_name(optarg);
- break;
- case 'b':
- browse = !browse;
- break;
- case 'A':
- dns_serve = True;
+ add_domain_entry(optarg,bcast_ip);
break;
case 'H':
strcpy(host_file,optarg);
break;
case 'I':
- {
- unsigned long a = interpret_addr(optarg);
- putip((char *)&myip,(char *)&a);
- got_myip = True;
- }
+ myip = *interpret_addr2(optarg);
+ got_myip = True;
break;
case 'B':
- {
- unsigned long a = interpret_addr(optarg);
- putip((char *)&bcast_ip,(char *)&a);
- got_bcast = True;
- }
+ bcast_ip = *interpret_addr2(optarg);
+ got_bcast = True;
break;
case 'N':
- {
- unsigned long a = interpret_addr(optarg);
- putip((char *)&Netmask,(char *)&a);
- got_nmask = True;
- }
+ Netmask = *interpret_addr2(optarg);
+ got_nmask = True;
break;
case 'n':
strcpy(myname,optarg);
break;
- case 'P':
- {
- extern BOOL passive;
- passive = True;
- }
- break;
- case 'S':
- dns_serve = !dns_serve;
- break;
case 'l':
sprintf(debugf,"%s.nmb",optarg);
break;
@@ -1888,18 +1994,6 @@
strcpy(scope,optarg);
strupper(scope);
break;
- case 'L':
- strcpy(lookup,optarg);
- break;
- case 'M':
- if (*optarg == '-') {
- strcpy(lookup,"\01\02__MSBROWSE__\02");
- lookup_type = 1;
- } else {
- strcpy(lookup,optarg);
- lookup_type = 0x1d;
- }
- break;
case 'D':
is_daemon = True;
break;
@@ -1914,14 +2008,12 @@
exit(0);
break;
default:
- usage(argv[0]);
- exit(1);
+ if (!is_a_socket(0))
+ usage(argv[0]);
+ break;
}
- if (*lookup)
- DEBUGLEVEL++;
-
if (DEBUGLEVEL > 10)
{
extern FILE *login,*logout;
@@ -1932,16 +2024,12 @@
logout = fopen(fname,"w");
}
- if (*lookup)
- {
- if (dbf)
- fclose(dbf);
- dbf = stdout;
- }
-
DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
+ if (!reload_services(False))
+ return(-1);
+
if (*host_file)
{
load_hosts_file(host_file);
@@ -1950,34 +2038,12 @@
init_structs();
- if (*lookup) {
- BOOL bcast = True;
- int retries = 2;
- char *p = strchr(lookup,'#');
- struct in_addr ip;
- if (p) {
- *p = 0;
- sscanf(p+1,"%x",&lookup_type);
- bcast = False;
- retries = 1;
- }
- if (!open_sockets(True,port)) return(1);
- while (retries--)
- if (name_query(lookup,lookup_type,bcast,bcast_ip,&ip,NULL)) {
- printf("%s %s\n",inet_ntoa(ip),lookup);
- name_status(lookup,lookup_type,ip,NULL,NULL);
- return(0);
- }
- printf("couldn't find name %s\n",lookup);
- return(0);
- }
-
- if (!*comment)
- strcpy(comment,"Samba %v");
- string_sub(comment,"%v",VERSION);
- string_sub(comment,"%h",myhostname);
+ if (!*ServerComment)
+ strcpy(ServerComment,"Samba %v");
+ string_sub(ServerComment,"%v",VERSION);
+ string_sub(ServerComment,"%h",myhostname);
- check_names();
+ add_my_names();
DEBUG(3,("Checked names\n"));
@@ -1990,6 +2056,7 @@
is_daemon = True;
}
+
if (is_daemon) {
DEBUG(2,("%s becoming a daemon\n",timestring()));
become_daemon();
diff -u -r --new-file last-version/source/nameserv2.c samba-1.9.15/source/nameserv2.c
--- last-version/source/nameserv2.c Sun Nov 12 21:35:59 1995
+++ samba-1.9.15/source/nameserv2.c Tue Nov 14 21:40:10 1995
@@ -82,19 +82,26 @@
/* here are my election parameters */
/* NTAS uses 2, NT uses 1, WfWg uses 0 */
-#define OS_LEVEL 3
-#define PREFERRED_MASTER 1
#define MAINTAIN_LIST 1
#define ELECTION_VERSION 1
static BOOL RunningElection = False;
-static BOOL needelection = True;
+static BOOL needelection = False;
static int ElectionCount = 0;
static int StartupTime =0;
-static uint32 ElectionCriterion =
-(OS_LEVEL<<28)|(PREFERRED_MASTER<<3)|(MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
+
+
+/* WfWg uses 01040b01 */
+/* Win95 uses 01041501 */
+/* NTAS uses ?? */
+static uint32 ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
+
+/* we currently support being the master for just one group. Being the
+ master for more than one group might be tricky as NetServerEnum is
+ often asked for a list without naming the group */
static fstring PrimaryGroup="";
+#define AM_MASTER (PrimaryGroup[0] && (ServerType & SV_TYPE_MASTER_BROWSER))
#define MSBROWSE "\001\002__MSBROWSE__\002"
@@ -107,8 +114,7 @@
DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
dump_names();
- if (!is_daemon)
- exit(1);
+ reload_services(True);
BlockSignals(False);
#ifndef DONT_REINSTALL_SIG
@@ -334,7 +340,7 @@
n = n2;
}
- if (ttl) n->death_time = time(NULL)+ttl;
+ if (ttl) n->death_time = time(NULL)+ttl*3;
n->ip = ip;
n->unique = unique;
n->source = source;
@@ -407,7 +413,7 @@
StrnCpy(s->name,name,sizeof(s->name)-1);
StrnCpy(s->comment,comment,sizeof(s->comment)-1);
s->servertype = servertype;
- s->death_time = ttl?time(NULL)+ttl:0;
+ s->death_time = ttl?time(NULL)+ttl*3:0;
strupper(s->name);
if (s->servertype & SV_TYPE_DOMAIN_ENUM) strupper(s->comment);
@@ -433,6 +439,7 @@
add_host_entry("__SAMBA__",0x0,True,0,SELF,ip);
add_host_entry(myname,0x20,True,0,SELF,ip);
add_host_entry(myname,0x0,True,0,SELF,ip);
+ add_host_entry(myname,0x1f,True,0,SELF,ip); /* used for chat, I think */
if (!domainlist)
add_domain_entry(lp_workgroup(),bcast_ip);
add_server_entry(myname,
@@ -442,9 +449,48 @@
/*******************************************************************
- delete old names from the namelist
+ write out browse.dat
******************************************************************/
-static void housekeeping(void)
+static void write_browse_list(void)
+{
+ struct server_record *s;
+ pstring fname,fnamenew;
+ FILE *f;
+
+ updatecount++;
+
+ strcpy(fname,lp_lockdir());
+ trim_string(fname,NULL,"/");
+ strcat(fname,"/");
+ strcat(fname,SERVER_LIST);
+ strcpy(fnamenew,fname);
+ strcat(fnamenew,".");
+
+ f = fopen(fnamenew,"w");
+
+ if (!f) {
+ DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
+ return;
+ }
+
+ for (s=serverlist; s ; s = s->next) {
+ /* don't list domains I don't have a master for */
+ if ((s->servertype & SV_TYPE_DOMAIN_ENUM) && !s->comment[0]) continue;
+
+ fprintf(f,"\"%s\"\t%08x\t\"%s\"\n",s->name,s->servertype,s->comment);
+ }
+
+
+ fclose(f);
+ unlink(fname);
+ rename(fnamenew,fname);
+ DEBUG(3,("Wrote browse list %s\n",fname));
+}
+
+/*******************************************************************
+ expire old names in the namelist and serverlist
+ ******************************************************************/
+static void expire_names(void)
{
static time_t lastrun=0;
time_t t = time(NULL);
@@ -453,7 +499,6 @@
struct server_record *s;
struct server_record *nexts;
- /* don't run this to often */
if (!lastrun) lastrun = t;
if (t < lastrun + 5) return;
lastrun = t;
@@ -477,6 +522,7 @@
for (s = serverlist; s; s = nexts) {
if (s->death_time && s->death_time < t) {
DEBUG(3,("Removing dead server %s\n",s->name));
+ updatedlists = True;
nexts = s->next;
if (s->prev) s->prev->next = s->next;
if (s->next) s->next->prev = s->prev;
@@ -486,44 +532,38 @@
nexts = s->next;
}
}
-
-
- /* write out the browse.dat database for smbd to get */
- if (!updatedlists) return;
- updatedlists = False;
- updatecount++;
- {
- pstring fname,fnamenew;
- FILE *f;
+}
- strcpy(fname,lp_lockdir());
- trim_string(fname,NULL,"/");
- strcat(fname,"/");
- strcat(fname,SERVER_LIST);
- strcpy(fnamenew,fname);
- strcat(fnamenew,".");
- f = fopen(fnamenew,"w");
+/*******************************************************************
+ delete old names from the namelist
+ ******************************************************************/
+static void housekeeping(void)
+{
+ time_t t = time(NULL);
- if (!f) {
- DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
- return;
- }
+ expire_names();
- for (s=serverlist; s ; s = s->next) {
- /* don't list domains I don't have a master for */
- if ((s->servertype & SV_TYPE_DOMAIN_ENUM) && !s->comment[0]) continue;
+ /* write out the browse.dat database for smbd to get */
+ if (updatedlists) {
+ write_browse_list();
+ updatedlists = False;
+ }
- fprintf(f,"\"%s\"\t%08x\t\"%s\"\n",s->name,s->servertype,s->comment);
+ {
+ /* occasionally check to see if the master browser is around */
+ static time_t lastrun=0;
+ if (!lastrun) lastrun = t;
+ if (t < lastrun + 5*60) return;
+ lastrun = t;
+
+ if (!AM_MASTER && *PrimaryGroup &&
+ !name_query(ClientNMB,PrimaryGroup,0x1d,True,False,
+ bcast_ip,NULL,queue_packet)) {
+ DEBUG(2,("Forcing election on %s\n",PrimaryGroup));
+ needelection = True;
}
-
-
- fclose(f);
- unlink(fname);
- rename(fnamenew,fname);
- DEBUG(3,("Wrote browse list %s\n",fname));
}
-
}
@@ -630,11 +670,11 @@
******************************************************************/
static BOOL same_net(struct in_addr ip1,struct in_addr ip2)
{
- unsigned int net1,net2,nmask;
+ unsigned long net1,net2,nmask;
- putip((char *)&nmask,(char *)&Netmask);
- putip((char *)&net1,(char *)&ip1);
- putip((char *)&net2,(char *)&ip2);
+ nmask = ntohl(Netmask.s_addr);
+ net1 = ntohl(ip1.s_addr);
+ net2 = ntohl(ip2.s_addr);
return((net1 & nmask) == (net2 & nmask));
}
@@ -779,11 +819,14 @@
pstring outbuf;
char *p;
char *namep;
+ char *stypep;
char *commentp;
if (needannounce) {
- d->announce_interval = 0;
- d->lastannounce_time = t - 1;
+ /* drop back to a max 3 minute announce - this is to prevent a
+ single lost packet from stuffing things up for too long */
+ d->announce_interval = MIN(d->announce_interval,3*60);
+ d->lastannounce_time = t - (d->announce_interval+1);
}
/* announce every minute at first then progress to every 12 mins */
@@ -813,6 +856,7 @@
strupper(p+5);
CVAL(p,21) = 2; /* major version */
CVAL(p,22) = 0; /* minor version */
+ stypep = p+23;
SIVAL(p,23,ServerType);
SSVAL(p,27,0xaa55); /* browse signature */
SSVAL(p,29,1); /* browse version */
@@ -824,8 +868,10 @@
send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
my_name,d->name,0,0x1d,d->bcast_ip,myip);
- if ((ServerType & SV_TYPE_MASTER_BROWSER) &&
- *PrimaryGroup &&
+ /* if I'm the master then I also need to do a local master and
+ domain announcement */
+
+ if (AM_MASTER &&
strequal(d->name,PrimaryGroup) &&
ip_equal(bcast_ip,d->bcast_ip)) {
@@ -840,6 +886,7 @@
strupper(namep);
StrnCpy(commentp,myname,15);
strupper(commentp);
+ SIVAL(stypep,0,(unsigned)0x80000000);
p = commentp + strlen(commentp) + 1;
send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
@@ -875,10 +922,39 @@
}
+/*******************************************************************
+ am I listening on a name. Should check name_type as well
+
+ This is primarily used to prevent us gathering server lists from
+ other workgroups we aren't a part of
+ ******************************************************************/
+static BOOL listening(struct nmb_name *n)
+{
+ if (!strequal(n->scope,scope)) return(False);
+
+ if (strequal(n->name,myname) ||
+ strequal(n->name,PrimaryGroup) ||
+ strequal(n->name,MSBROWSE))
+ return(True);
+
+ return(False);
+}
/*******************************************************************
process a domain announcement frame
+
+ Announce frames come in 3 types. Servers send host announcements
+ (command=1) to let the master browswer know they are
+ available. Master browsers send local master announcements
+ (command=15) to let other masters and backups that they are the
+ master. They also send domain announcements (command=12) to register
+ the domain
+
+ The comment field of domain announcements contains the master
+ browser name. The servertype is used by NetServerEnum to select
+ resources. We just have to pass it to smbd (via browser.dat) and let
+ the client choose using bit masks.
******************************************************************/
static void process_announce(struct packet_struct *p,int command,char *buf)
{
@@ -900,12 +976,24 @@
if (strequal(dgram->source_name.name,myname)) return;
+ if (!listening(&dgram->dest_name)) return;
+
+ /* add them to our browse list */
add_server_entry(name,servertype,ttl,comment);
}
/*******************************************************************
process a backup list request
+
+ A client send a backup list request to ask for a list of servers on
+ the net that maintain server lists for a domain. A server is then
+ chosen from this list to send NetServerEnum commands to to list
+ available servers.
+
+ Currently samba only sends back one name in the backup list, its
+ wn. For larger nets we'll have to add backups and send "become
+ backup" requests occasionally.
******************************************************************/
static void process_backup_list(struct packet_struct *p,char *buf)
{
@@ -921,10 +1009,12 @@
if (count <= 0) return;
- if (!*PrimaryGroup || !(ServerType & SV_TYPE_MASTER_BROWSER) ||
+ if (!AM_MASTER ||
!strequal(PrimaryGroup,dgram->dest_name.name))
return;
+ if (!listening(&dgram->dest_name)) return;
+
send_backup_list(myname,token,
&dgram->source_name,
p->ip);
@@ -957,6 +1047,8 @@
/*******************************************************************
process a election packet
+
+ An election dynamically decides who will be the master.
******************************************************************/
static void process_election(struct packet_struct *p,char *buf)
{
@@ -972,29 +1064,33 @@
name,version,criterion,timeup));
if (strequal(dgram->source_name.name,myname)) return;
- if (!*PrimaryGroup ||
- !strequal(dgram->dest_name.name,PrimaryGroup)) return;
+
+ if (!listening(&dgram->dest_name)) return;
if (win_election(version,criterion,timeup,name)) {
if (!RunningElection) {
- DEBUG(3,(">>> Starting election on %s <<<\n",PrimaryGroup));
needelection = True;
ElectionCount=0;
}
} else {
- RunningElection = False;
needelection = False;
- /* if we are the master then remove our masterly name */
- if (ServerType & SV_TYPE_MASTER_BROWSER) {
+ if (RunningElection) {
+ RunningElection = False;
DEBUG(3,(">>> Lost election on %s <<<\n",PrimaryGroup));
- become_nonmaster();
+
+ /* if we are the master then remove our masterly names */
+ if (AM_MASTER)
+ become_nonmaster();
}
}
-
}
+
/*******************************************************************
process a announcement request
+
+ clients send these when they want everyone to send an announcement
+ immediately. This can cause quite a storm of packets!
******************************************************************/
static void process_announce_request(struct packet_struct *p,char *buf)
{
@@ -1174,7 +1270,6 @@
DEBUG(3,("Name release on name %s rcode=%d\n",
namestr(&nmb->question.question_name),rcode));
-
if (bcast) return;
/* Send a NAME RELEASE RESPONSE */
@@ -1246,14 +1341,14 @@
rcode = 6;
} else {
n->ip = ip;
- n->death_time = ttl?p->timestamp+ttl:0;
+ n->death_time = ttl?p->timestamp+ttl*3:0;
DEBUG(3,("%s changed owner to %s\n",
namestr(&n->name),inet_ntoa(n->ip)));
}
} else {
/* refresh the name */
if (n->source != SELF)
- n->death_time = ttl?p->timestamp + ttl:0;
+ n->death_time = ttl?p->timestamp + ttl*3:0;
}
} else {
/* add the name to our database */
@@ -1351,7 +1446,7 @@
nmb2->answers->ttl = 0;
for (count=0, n = namelist ; n; n = n->next) {
- if (n->source != SELF && n->source != LMHOSTS) continue;
+ if (n->source != SELF) continue;
count++;
}
@@ -1365,7 +1460,7 @@
for (n = namelist ; n; n = n->next)
{
- if (n->source != SELF && n->source != LMHOSTS) continue;
+ if (n->source != SELF) continue;
bzero(buf,18);
strcpy(buf,n->name.name);
@@ -1459,10 +1554,10 @@
return;
}
- /* don't respond to bcast queries for addresses on the same net as the machine
- doing the querying unless its our IP (or something from LMHOSTS) */
+ /* don't respond to bcast queries for addresses on the same net as the
+ machine doing the querying unless its our IP */
if (bcast &&
- n->source != SELF && n->source != LMHOSTS &&
+ n->source != SELF &&
same_net(n->ip,p->ip)) {
DEBUG(3,("same net\n"));
return;
@@ -1479,7 +1574,7 @@
}
/* if the IP is 0 then substitute my IP - we should see which one is on the
- right interface for the caller to do this right */
+ right interface for the caller to do this right XXX */
if (zero_ip(retip)) retip = myip;
DEBUG(3,("OK %s rcode=%d\n",inet_ntoa(retip),rcode));
@@ -1636,6 +1731,7 @@
struct timeval timeout;
if (needelection && *PrimaryGroup && !RunningElection) {
+ DEBUG(3,(">>> Starting election on %s <<<\n",PrimaryGroup));
ElectionCount = 0;
RunningElection = True;
needelection = False;
@@ -1644,6 +1740,8 @@
FD_ZERO(&fds);
FD_SET(ClientNMB,&fds);
FD_SET(ClientDGRAM,&fds);
+ /* during elections we need to send election packets at one
+ second intervals */
timeout.tv_sec = RunningElection?1:NMBD_SELECT_LOOP;
timeout.tv_usec = 0;
@@ -1705,6 +1803,40 @@
}
+/*******************************************************************
+ check that a IP, bcast and netmask and consistent. Must be a 1s
+ broadcast
+ ******************************************************************/
+static BOOL ip_consistent(struct in_addr ip,struct in_addr bcast,
+ struct in_addr nmask)
+{
+ unsigned long a_ip,a_bcast,a_nmask;
+
+ a_ip = ntohl(ip.s_addr);
+ a_bcast = ntohl(bcast.s_addr);
+ a_nmask = ntohl(nmask.s_addr);
+
+ /* check the netmask is sane */
+ if (((a_nmask>>24)&0xFF) != 0xFF) {
+ DEBUG(0,("Insane netmask %s\n",inet_ntoa(nmask)));
+ return(False);
+ }
+
+ /* check the IP and bcast are on the same net */
+ if ((a_ip&a_nmask) != (a_bcast&a_nmask)) {
+ DEBUG(0,("IP and broadcast are on different nets!\n"));
+ return(False);
+ }
+
+ /* check the IP and bcast are on the same net */
+ if ((a_bcast|a_nmask) != 0xFFFFFFFF) {
+ DEBUG(0,("Not a ones based broadcast %s\n",inet_ntoa(bcast)));
+ return(False);
+ }
+
+ return(True);
+}
+
/****************************************************************************
initialise connect, service and file structs
****************************************************************************/
@@ -1733,11 +1865,14 @@
Netmask = ip2;
}
- DEBUG(1,("Using IP %s ",inet_ntoa(myip))); /* core dump reported
- doing this. Why?? XXXXX */
+ DEBUG(1,("Using IP %s ",inet_ntoa(myip)));
DEBUG(1,("broadcast %s ",inet_ntoa(bcast_ip)));
DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));
+ if (!ip_consistent(myip,bcast_ip,Netmask)) {
+ DEBUG(0,("WARNING: The IP address, broadcast and Netmask are not consistent\n"));
+ DEBUG(0,("You are likely to experience problems with this setup!\n"));
+ }
}
if (! *myname) {
@@ -1747,6 +1882,13 @@
if (p) *p = 0;
}
+ if (lp_preferred_master()) {
+ needelection = True;
+ ElectionCriterion |= (1<<3);
+ }
+
+ ElectionCriterion |= (lp_os_level() << 28);
+
return True;
}
@@ -1866,8 +2008,9 @@
exit(0);
break;
default:
- usage(argv[0]);
- exit(1);
+ if (!is_a_socket(0))
+ usage(argv[0]);
+ break;
}
diff -u -r --new-file last-version/source/nmblib.c samba-1.9.15/source/nmblib.c
--- last-version/source/nmblib.c Sun Nov 12 15:16:26 1995
+++ samba-1.9.15/source/nmblib.c Tue Nov 14 21:23:08 1995
@@ -1,7 +1,7 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
- NBT netbios routines and daemon - version 2
+ NBT netbios library routines
Copyright (C) Andrew Tridgell 1994-1995
This program is free software; you can redistribute it and/or modify
@@ -649,7 +649,9 @@
/****************************************************************************
- do a netbios name status to a host
+ do a netbios name status query on a host
+
+ the "master" parameter is a hack used for finding workgroups.
**************************************************************************/
BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
struct in_addr to_ip,char *master,void (*fn)())
@@ -818,7 +820,8 @@
struct nmb_packet *nmb2 = &p2->packet.nmb;
if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
!nmb2->header.response) {
- /* its not for us - maybe deal with it later (put it on the queue?) */
+ /* its not for us - maybe deal with it later
+ (put it on the queue?) */
if (fn)
fn(p2);
else
@@ -836,12 +839,15 @@
continue;
}
- putip((char *)ip,&nmb2->answers->rdata[2]);
- DEBUG(2,("Got a positive name query response from %s",
- inet_ntoa(p2->ip)));
- DEBUG(2,(" (%s)\n",inet_ntoa(*ip)));
+ if (ip) {
+ putip((char *)ip,&nmb2->answers->rdata[2]);
+ DEBUG(fn?3:2,("Got a positive name query response from %s",
+ inet_ntoa(p2->ip)));
+ DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip)));
+ }
found=True; retries=0;
free_packet(p2);
+ if (fn) break;
}
}
@@ -851,6 +857,9 @@
/****************************************************************************
construct and send a netbios DGRAM
+
+ Note that this currently sends all answers to port 138. thats the
+ wrong things to do! I should send to the requestors port. XXX
**************************************************************************/
BOOL send_udp_dgram(int fd,char *buf,int len,
char *srcname,char *dstname,
diff -u -r --new-file last-version/source/reply.c samba-1.9.15/source/reply.c
--- last-version/source/reply.c Mon Nov 6 16:14:59 1995
+++ samba-1.9.15/source/reply.c Mon Nov 13 19:30:23 1995
@@ -707,22 +707,15 @@
/* turn strings of spaces into a . */
{
- p = strrchr(mask,' ');
- if (p)
+ trim_string(mask,NULL," ");
+ if ((p = strrchr(mask,' ')))
{
- if (!p[1])
- {
- while (*p == ' ') {*p = 0;p--;}
- }
- else
- {
- fstring ext;
- strcpy(ext,p+1);
- *p = 0;
- trim_string(mask,NULL," ");
- strcat(mask,".");
- strcat(mask,ext);
- }
+ fstring ext;
+ strcpy(ext,p+1);
+ *p = 0;
+ trim_string(mask,NULL," ");
+ strcat(mask,".");
+ strcat(mask,ext);
}
}
diff -u -r --new-file last-version/source/server.c samba-1.9.15/source/server.c
--- last-version/source/server.c Sun Nov 12 13:21:30 1995
+++ samba-1.9.15/source/server.c Tue Nov 14 23:15:32 1995
@@ -185,6 +185,11 @@
if (S_ISDIR(sbuf->st_mode))
result = aDIR | (result & aRONLY);
+#if LINKS_READ_ONLY
+ if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
+ result |= aRONLY;
+#endif
+
/* hide files with a name starting with a . */
if (lp_hide_dot_files(SNUM(cnum)))
{
@@ -2725,7 +2730,6 @@
int reply_lanman1(char *outbuf)
{
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int outsize;
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
@@ -2733,13 +2737,20 @@
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
- outsize = set_message(outbuf,13,doencrypt?8:0,True);
+ set_message(outbuf,13,doencrypt?8:0,True);
SSVAL(outbuf,smb_vwv1,secword);
#ifdef SMB_PASSWD
/* Create a token value and add it to the outgoing packet. */
if (doencrypt)
generate_next_challenge(smb_buf(outbuf));
#endif
+
+ Protocol = PROTOCOL_LANMAN1;
+
+ if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
+ DEBUG(3,("using password server validation\n"));
+ }
+
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
SSVAL(outbuf,smb_vwv2,maxxmit);
SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
@@ -2751,9 +2762,7 @@
put_dos_date(outbuf,smb_vwv8,t);
- Protocol = PROTOCOL_LANMAN1;
-
- return outsize;
+ return (smb_len(outbuf)+4);
}
@@ -2763,7 +2772,6 @@
int reply_lanman2(char *outbuf)
{
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int outsize;
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
@@ -2771,7 +2779,7 @@
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
- outsize = set_message(outbuf,13,doencrypt?8:0,True);
+ set_message(outbuf,13,doencrypt?8:0,True);
SSVAL(outbuf,smb_vwv1,secword);
#ifdef SMB_PASSWD
/* Create a token value and add it to the outgoing packet. */
@@ -2795,7 +2803,7 @@
SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
put_dos_date(outbuf,smb_vwv8,t);
- return (outsize);
+ return (smb_len(outbuf)+4);
}
/****************************************************************************
diff -u -r --new-file last-version/source/smb.h samba-1.9.15/source/smb.h
--- last-version/source/smb.h Sun Nov 12 13:21:29 1995
+++ samba-1.9.15/source/smb.h Tue Nov 14 21:55:41 1995
@@ -767,7 +767,7 @@
char *smb_trans2_data(char *buf);
BOOL strequal(char *,char *);
BOOL strcsequal(char *,char *);
-BOOL mask_match( char *str, char *regexp, int case_sig, BOOL autoext);
+BOOL mask_match( char *str, char *regexp, int case_sig, BOOL trans2);
int dos_mode(int ,char *,struct stat *);
char *timestring();
BOOL ip_equal(struct in_addr ip1,struct in_addr ip2);
diff -u -r --new-file last-version/source/status.c samba-1.9.15/source/status.c
--- last-version/source/status.c Sun Nov 12 13:08:59 1995
+++ samba-1.9.15/source/status.c Mon Nov 13 15:53:03 1995
@@ -30,6 +30,15 @@
extern int DEBUGLEVEL;
extern FILE *dbf;
+static pstring Ucrit_username = ""; /* added by OH */
+int Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */
+int Ucrit_MaxPid=0; /* added by OH */
+unsigned int Ucrit_IsActive = 0; /* added by OH */
+void Ucrit_addUsername(pstring username); /* added by OH */
+unsigned int Ucrit_checkUsername(pstring username); /* added by OH */
+void Ucrit_addPid(int pid); /* added by OH */
+unsigned int Ucrit_checkPid(int pid); /* added by OH */
+
int main(int argc, char *argv[])
{
FILE *f;
@@ -42,6 +51,7 @@
char *s;
BOOL firstopen=True;
BOOL processes_only=False;
+ int last_pid=0;
charset_initialise();
@@ -53,7 +63,7 @@
return(1);
}
- while ((c = getopt(argc, argv, "pds:")) != EOF) {
+ while ((c = getopt(argc, argv, "pdsu:")) != EOF) {
switch (c) {
case 'd':
verbose = 1;
@@ -64,13 +74,18 @@
case 's':
strcpy(servicesf, optarg);
break;
+ case 'u': /* added by OH */
+ Ucrit_addUsername(optarg); /* added by OH */
+ break;
default:
- fprintf(stderr, "Usage: %s [-p] [-d] [-s configfile]\n", *argv);
+ fprintf(stderr, "Usage: %s [-d] [-p] [-s configfile] [-u username]\n", *argv); /* changed by OH */
return (-1);
}
}
- if (!lp_load(servicesf,True)) {
+
+
+ if (!lp_load(servicesf,False)) {
fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
return (-1);
}
@@ -97,28 +112,30 @@
if (!processes_only) {
printf("\nSamba version %s\n",VERSION);
-
+
printf("Service uid gid pid machine\n");
printf("----------------------------------------------\n");
}
while (!feof(f))
{
- static int last_pid = 0;
if (fread(&crec,sizeof(crec),1,f) != 1)
break;
- if (crec.magic == 0x280267 && process_exists(crec.pid)) {
+ if ( crec.magic == 0x280267 && process_exists(crec.pid)
+ && Ucrit_checkUsername(uidtoname(crec.uid)) /* added by OH */
+ )
+ {
+ Ucrit_addPid(crec.pid); /* added by OH */
if (processes_only) {
if (last_pid != crec.pid)
printf("%d\n",crec.pid);
last_pid = crec.pid; /* XXXX we can still get repeats, have to
add a sort at some time */
}
- else
+ else
printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s",
crec.name,uidtoname(crec.uid),gidtoname(crec.gid),crec.pid,
- crec.machine,crec.addr,
- asctime(LocalTime(&crec.start,GMT_TO_LOCAL)));
+ crec.machine,crec.addr,asctime(LocalTime(&crec.start,0)));
}
}
fclose(f);
@@ -155,9 +172,12 @@
mode = IVAL(buf,4);
pid = IVAL(buf,8);
+ if ( !Ucrit_checkPid(pid) ) /* added by OH */
+ continue;
+
if (IVAL(buf,12) != LOCKING_VERSION || !process_exists(pid)) {
if (unlink(lname)==0)
- printf("Deleted stale share file %s\n",s);
+ printf("Deleted stale share file %s\n",s);
continue;
}
@@ -194,5 +214,38 @@
printf("No locked files\n");
return (0);
+}
+
+/* added by OH */
+void Ucrit_addUsername(pstring username)
+{
+ strcpy(Ucrit_username, username);
+ if(strlen(Ucrit_username) > 0)
+ Ucrit_IsActive = 1;
+}
+
+unsigned int Ucrit_checkUsername(pstring username)
+{
+ if ( !Ucrit_IsActive) return 1;
+ if (strcmp(Ucrit_username,username) ==0) return 1;
+ return 0;
+}
+
+void Ucrit_addPid(int pid)
+{
+ int i;
+ if ( !Ucrit_IsActive) return;
+ for (i=0;i<Ucrit_MaxPid;i++)
+ if( pid == Ucrit_pid[i] ) return;
+ Ucrit_pid[Ucrit_MaxPid++] = pid;
+}
+
+unsigned int Ucrit_checkPid(int pid)
+{
+ int i;
+ if ( !Ucrit_IsActive) return 1;
+ for (i=0;i<Ucrit_MaxPid;i++)
+ if( pid == Ucrit_pid[i] ) return 1;
+ return 0;
}
diff -u -r --new-file last-version/source/system.c samba-1.9.15/source/system.c
--- last-version/source/system.c Thu Sep 21 21:01:05 1995
+++ samba-1.9.15/source/system.c Mon Nov 13 17:35:06 1995
@@ -96,7 +96,7 @@
do {
if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
errno = 0;
- selrtn = select(255,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
+ selrtn = select(FD_SETSIZE,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
} while (selrtn<0 && errno == EINTR);
return(selrtn);
diff -u -r --new-file last-version/source/trans2.c samba-1.9.15/source/trans2.c
--- last-version/source/trans2.c Sat Nov 11 00:19:11 1995
+++ samba-1.9.15/source/trans2.c Tue Nov 14 21:58:26 1995
@@ -300,7 +300,7 @@
strcpy(fname,dname);
- if(mask_match(fname, mask, case_sensitive, False))
+ if(mask_match(fname, mask, case_sensitive, True))
{
BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
if (dont_descend && !isdots)
diff -u -r --new-file last-version/source/username.c samba-1.9.15/source/username.c
--- last-version/source/username.c Sat Sep 2 14:33:27 1995
+++ samba-1.9.15/source/username.c Mon Nov 13 16:30:59 1995
@@ -202,19 +202,19 @@
return(True);
#ifdef NETGROUP
- if (*p == '@')
+ if (*tok == '@')
{
static char *mydomain = NULL;
if (mydomain == 0)
yp_get_default_domain(&mydomain);
DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
- user, mydomain, p+1));
+ user, mydomain, &tok[1]));
DEBUG(5,("innetgr is %s\n",
- innetgr(p + 1, (char *) 0, user, mydomain)
+ innetgr(&tok[1], (char *) 0, user, mydomain)
? "TRUE" : "FALSE"));
- if (innetgr(p + 1, (char *)0, user, mydomain))
+ if (innetgr(&tok[1], (char *)0, user, mydomain))
return (True);
}
#endif
diff -u -r --new-file last-version/source/util.c samba-1.9.15/source/util.c
--- last-version/source/util.c Sun Nov 12 13:21:27 1995
+++ samba-1.9.15/source/util.c Tue Nov 14 22:09:36 1995
@@ -1043,6 +1043,20 @@
}
/*******************************************************************
+ case insensitive string compararison, length limited
+********************************************************************/
+int StrnCaseCmp(char *s, char *t, int n)
+{
+ while (n-- && *s && *t) {
+ if (tolower(*s) != tolower(*t)) return(tolower(*s) - tolower(*t));
+ s++; t++;
+ }
+ if (n) return(tolower(*s) - tolower(*t));
+
+ return(0);
+}
+
+/*******************************************************************
compare 2 strings
********************************************************************/
BOOL strequal(char *s1,char *s2)
@@ -2831,7 +2845,7 @@
* simplified regexp that takes * and ? only. Case can be
* significant or not.
*********************************************************/
-BOOL mask_match( char *str, char *regexp, int case_sig, BOOL autoext)
+BOOL mask_match(char *str, char *regexp, int case_sig, BOOL trans2)
{
char *p;
pstring p1, p2;
@@ -2860,34 +2874,31 @@
DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
- if ((p=strrchr(p1,'.')))
- {
+ if (trans2) {
+ strcpy(ebase,p1);
+ strcpy(sbase,p2);
+ } else {
+ if ((p=strrchr(p1,'.'))) {
*p = 0;
strcpy(ebase,p1);
strcpy(eext,p+1);
- }
- else
- {
+ } else {
strcpy(ebase,p1);
- if (autoext)
- strcpy(eext,"*");
- else
- eext[0] = 0;
+ eext[0] = 0;
}
- if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.')))
- {
- *p = 0;
- strcpy(sbase,p2);
- strcpy(sext,p+1);
- }
- else
- {
- strcpy(sbase,p2);
- strcpy(sext,"");
- }
+ if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
+ *p = 0;
+ strcpy(sbase,p2);
+ strcpy(sext,p+1);
+ } else {
+ strcpy(sbase,p2);
+ strcpy(sext,"");
+ }
+ }
- matched = do_match(sbase,ebase,case_sig) && do_match(sext,eext,case_sig);
+ matched = do_match(sbase,ebase,case_sig) &&
+ (trans2 || do_match(sext,eext,case_sig));
DEBUG(5,("mask_match returning %d\n", matched));
@@ -3487,8 +3498,8 @@
BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
{
unsigned long a1,a2;
- putip((char *)&a1,(char *)&ip1);
- putip((char *)&a2,(char *)&ip2);
+ a1 = ntohl(ip1.s_addr);
+ a2 = ntohl(ip2.s_addr);
return(a1 == a2);
}
@@ -4042,6 +4053,10 @@
****************************************************************************/
int initgroups(char *name,gid_t id)
{
+#ifdef NO_SETGROUPS
+ /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
+ return(0);
+#else
gid_t grouplst[NGROUPS_MAX];
int i,j;
struct group *g;
@@ -4068,6 +4083,7 @@
}
endgrent();
return(setgroups(i,grouplst));
+#endif
}
#endif
diff -u -r --new-file last-version/source/version.h samba-1.9.15/source/version.h
--- last-version/source/version.h Sun Nov 12 21:43:21 1995
+++ samba-1.9.15/source/version.h Wed Nov 15 00:11:42 1995
@@ -1 +1 @@
-#define VERSION "1.9.14p5"
+#define VERSION "1.9.15"